567 lines
21 KiB
C++
567 lines
21 KiB
C++
# Basic test for optimizer trace
|
|
|
|
--source include/have_optimizer_trace.inc
|
|
|
|
# This test gives different results when ps-protocol is enabled
|
|
# because in ps-protocol, we read OPTIMIZER_TRACE after
|
|
# 'EXECUTE stmt'; for subqueries the IN->EXISTS transformation is done
|
|
# at PREPARE time, and not re-done at EXECUTE time, so in normal
|
|
# protocol the trace talks about IN->EXISTS, but in ps-protocol it
|
|
# doesn't (as it's the EXECUTE trace and IN->EXISTS was done once for
|
|
# all at PREPARE; we see IN->EXISTS if we look at the trace of
|
|
# PREPARE).
|
|
# That's why we have two result files.
|
|
# This test is skipped in view-protocol because this changes queries
|
|
# submitted to the optimizer (from 'SELECT x FROM ... WHERE ... etc'
|
|
# to 'SELECT x FROM mysqltest_tmp_v') so changes trace.
|
|
# It's also skipped in sp-protocol for the same reason (SELECT becomes
|
|
# CALL).
|
|
|
|
# When adding tests here, try to have some of them use SELECT and
|
|
# others use EXPLAIN SELECT, to verify that both ways give sufficient
|
|
# tracing.
|
|
|
|
# should be empty
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
let $DEFAULT_TRACE_MEM_SIZE=1048576; # 1MB
|
|
eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
|
|
set @@session.optimizer_trace="enabled=on";
|
|
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
CREATE TABLE t5 (c int);
|
|
INSERT INTO t5 VALUES (NULL);
|
|
|
|
CREATE TABLE t6 (d int , KEY (d));
|
|
INSERT INTO t6 VALUES (NULL),(NULL);
|
|
|
|
SELECT (SELECT 1 FROM t6 WHERE d = c) AS RESULT FROM t5 ;
|
|
|
|
# some float values might not be identical on all platforms, we will see.
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
# check frequency of spaces
|
|
select (1-length(replace(TRACE, " ", ""))/length(TRACE))*100
|
|
from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# now all on one line
|
|
set optimizer_trace="one_line=on";
|
|
SELECT (SELECT 1 FROM t6 WHERE d = c) AS RESULT FROM t5 ;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
# check frequency of spaces
|
|
select (1-length(replace(TRACE, " ", ""))/length(TRACE))*100
|
|
from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# From now on, use end markers, easier to read
|
|
set end_markers_in_json=on;
|
|
set optimizer_trace="one_line=off";
|
|
|
|
# trace should be produced by EXPLAIN too
|
|
EXPLAIN SELECT (SELECT 1 FROM t6 WHERE d = ifnull(c,null)) AS RESULT FROM t5 ;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
SELECT /* should be last */ (SELECT 1 FROM t6 WHERE d = ifnull(c,null)) AS RESULT FROM t5 ;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
set @@session.optimizer_trace="enabled=off";
|
|
SELECT /* bug if you see this*/ (SELECT 1 FROM t6 WHERE d = ifnull(c,null)) AS RESULT FROM t5 ;
|
|
# should not see last statement but previous
|
|
select QUERY from information_schema.OPTIMIZER_TRACE;
|
|
|
|
set @@session.optimizer_trace="enabled=on";
|
|
|
|
# union in subquery
|
|
SELECT (SELECT 1 FROM t6 WHERE d = ifnull(c,null) UNION SELECT 2 FROM t6 WHERE d = ifnull(c,null)) AS RESULT FROM t5 ;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# union in subquery in WHERE clause
|
|
SELECT * FROM t5 WHERE 5 IN (SELECT 1 FROM t6 WHERE d = ifnull(c,null) UNION SELECT 2 FROM t6 WHERE d = ifnull(c,null));
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# Test max_mem_size: re-run same query with lower max_mem_size:
|
|
# save non-truncated trace but don't output it again
|
|
select (@query:=QUERY)+NULL, (@trace:=TRACE)+NULL from information_schema.OPTIMIZER_TRACE;
|
|
select length(@trace);
|
|
# The concatenation of query and trace above has length:
|
|
# - >@max_mem_size in normal mode
|
|
# - <@max_mem_size in ps-protocol mode (because IN->EXISTS is done at PREPARE
|
|
# and we trace only EXECUTE)
|
|
# - So in normal mode, the lines below verify truncation,
|
|
# whereas in ps-protocol mode they verify non-truncation.
|
|
set @max_mem_size=13807;
|
|
set optimizer_trace_max_mem_size=@max_mem_size;
|
|
select length(@query)+length(@trace) > @@optimizer_trace_max_mem_size;
|
|
SELECT * FROM t5 WHERE 5 IN (SELECT 1 FROM t6 WHERE d = ifnull(c,null) UNION SELECT 2 FROM t6 WHERE d = ifnull(c,null));
|
|
select (@missing_bytes:=missing_bytes_beyond_max_mem_size) from information_schema.OPTIMIZER_TRACE;
|
|
select (@query2:=QUERY)+NULL,(@trace2:=TRACE)+NULL from information_schema.OPTIMIZER_TRACE;
|
|
select length(@trace2),
|
|
(length(@trace2) + @missing_bytes) = length(@trace),
|
|
@query2 = @query;
|
|
# If truncated, trace length should be around the maximum, possibly a
|
|
# bit higher as we stop tracing after passing the maximum.
|
|
select length(@query2) + length(@trace2)
|
|
between (@@optimizer_trace_max_mem_size-200) and (@@optimizer_trace_max_mem_size+200);
|
|
# if truncated, trace should be a prefix of non-truncated trace
|
|
select instr(@trace, @trace2) = 1;
|
|
|
|
# Test that if the query is longer than max size, trace is not produced
|
|
set optimizer_trace_max_mem_size=1;
|
|
select 1;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
# Test that with max size == 0, even query is not produced
|
|
set optimizer_trace_max_mem_size=0;
|
|
select 1;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
eval set optimizer_trace_max_mem_size=$DEFAULT_TRACE_MEM_SIZE;
|
|
|
|
# semijoin
|
|
|
|
explain SELECT c FROM t5 where c+1 in (select d+1 from t6 where d is null);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# subquery materialization
|
|
|
|
set @old_opt_switch=@@optimizer_switch;
|
|
# The SET below must not be output, because only servers supporting
|
|
# semijoin will execute it (would make varying output).
|
|
if (`select locate('semijoin', @@optimizer_switch) > 0`)
|
|
{
|
|
--disable_query_log
|
|
set optimizer_switch="semijoin=off,subquery_materialization_cost_based=off";
|
|
--enable_query_log
|
|
}
|
|
explain SELECT c FROM t5 where c+1 in (select d+1 from t6 where d is null);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
set optimizer_switch=@old_opt_switch;
|
|
|
|
# 5.1-style subquery transformations
|
|
CREATE TABLE t1 (s1 CHAR(5),
|
|
s2 CHAR(5)) CHARSET utf8mb4;
|
|
INSERT INTO t1 VALUES ('z','?'),('y','!');
|
|
# > ANY -> > MIN...
|
|
explain select * from t1 where s1 > any (select s2 from t1);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
explain select * from t1 where s1 > any (select max(s2) from t1);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
# IN -> EXISTS
|
|
if (`select locate('semijoin', @@optimizer_switch) > 0`)
|
|
{
|
|
--disable_query_log
|
|
set optimizer_switch="semijoin=off,materialization=off";
|
|
--enable_query_log
|
|
}
|
|
explain select * from t1 where s1 in (select s2 from t1);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
explain select * from t1 where (s1,s2) in (select s2,s1 from t1);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
set optimizer_switch=@old_opt_switch;
|
|
drop table t1;
|
|
|
|
# explanation of plan choice
|
|
create table t1(a int);
|
|
create table t2(a int);
|
|
insert into t1 values(1),(2),(3);
|
|
insert into t2 values(1),(2);
|
|
# print many plans:
|
|
set @@session.optimizer_prune_level=0;
|
|
explain select * from t1,t2;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
# don't print plans:
|
|
select @@optimizer_trace_features;
|
|
set @@optimizer_trace_features="greedy_search=off";
|
|
explain select * from t1,t2;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
set @@optimizer_trace_features=default;
|
|
set @@session.optimizer_prune_level=default;
|
|
drop table t1, t2;
|
|
|
|
# test late decision to abandon subquery materialization due to BLOBs
|
|
# (from subselect_mat.test)
|
|
# force materialization to be always considered
|
|
if (`select locate('semijoin', @@optimizer_switch) > 0`)
|
|
{
|
|
--disable_query_log
|
|
set @@optimizer_switch='semijoin=off';
|
|
--enable_query_log
|
|
}
|
|
set @prefix_len = 6;
|
|
# BLOB == 16 (small blobs that could be stored in HEAP tables)
|
|
set @blob_len = 16;
|
|
set @suffix_len = @blob_len - @prefix_len;
|
|
create table t1_16 (a1 blob(16), a2 blob(16));
|
|
create table t2_16 (b1 blob(16), b2 blob(16));
|
|
create table t3_16 (c1 blob(16), c2 blob(16));
|
|
insert into t1_16 values
|
|
(concat('1 - 00', repeat('x', @suffix_len)), concat('2 - 00', repeat('x', @suffix_len)));
|
|
insert into t1_16 values
|
|
(concat('1 - 01', repeat('x', @suffix_len)), concat('2 - 01', repeat('x', @suffix_len)));
|
|
insert into t1_16 values
|
|
(concat('1 - 02', repeat('x', @suffix_len)), concat('2 - 02', repeat('x', @suffix_len)));
|
|
insert into t2_16 values
|
|
(concat('1 - 01', repeat('x', @suffix_len)), concat('2 - 01', repeat('x', @suffix_len)));
|
|
insert into t2_16 values
|
|
(concat('1 - 02', repeat('x', @suffix_len)), concat('2 - 02', repeat('x', @suffix_len)));
|
|
insert into t2_16 values
|
|
(concat('1 - 03', repeat('x', @suffix_len)), concat('2 - 03', repeat('x', @suffix_len)));
|
|
insert into t3_16 values
|
|
(concat('1 - 01', repeat('x', @suffix_len)), concat('2 - 01', repeat('x', @suffix_len)));
|
|
insert into t3_16 values
|
|
(concat('1 - 02', repeat('x', @suffix_len)), concat('2 - 02', repeat('x', @suffix_len)));
|
|
insert into t3_16 values
|
|
(concat('1 - 03', repeat('x', @suffix_len)), concat('2 - 03', repeat('x', @suffix_len)));
|
|
insert into t3_16 values
|
|
(concat('1 - 04', repeat('x', @suffix_len)), concat('2 - 04', repeat('x', @suffix_len)));
|
|
# single value transformer
|
|
explain select left(a1,7), left(a2,7)
|
|
from t1_16
|
|
where a1 in (select b1 from t2_16 where b1 > '0');
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
drop table t1_16,t2_16,t3_16;
|
|
set @@optimizer_switch=@old_opt_switch;
|
|
|
|
# test of outer-join preventing semijoin
|
|
# from subselect.test
|
|
|
|
CREATE table t1 ( c1 integer );
|
|
INSERT INTO t1 VALUES ( 1 );
|
|
INSERT INTO t1 VALUES ( 2 );
|
|
INSERT INTO t1 VALUES ( 3 );
|
|
|
|
CREATE TABLE t2 ( c2 integer );
|
|
INSERT INTO t2 VALUES ( 1 );
|
|
INSERT INTO t2 VALUES ( 4 );
|
|
INSERT INTO t2 VALUES ( 5 );
|
|
|
|
SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2
|
|
WHERE c2 IN ( SELECT c2 FROM t2 WHERE c2 IN ( 1 ) );
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# union in top-query
|
|
|
|
SELECT * FROM t1 WHERE c1=5 UNION SELECT * FROM t2 WHERE c2=5;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# two subqueries in top query
|
|
|
|
if (`select locate('semijoin', @@optimizer_switch) > 0`)
|
|
{
|
|
--disable_query_log
|
|
set optimizer_switch="semijoin=off";
|
|
--enable_query_log
|
|
}
|
|
|
|
explain
|
|
select * from t1
|
|
where concat(c1,'x') IN
|
|
(select left(c2,8) from t2)
|
|
and
|
|
concat(c1,'y') IN
|
|
(select left(c2,9) from t2);
|
|
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
set optimizer_switch=@old_opt_switch;
|
|
|
|
DROP TABLE t1,t2;
|
|
|
|
# two constant tables
|
|
|
|
create table t1 (a int);
|
|
insert into t1 values(1);
|
|
create table t2 (a int);
|
|
insert into t2 values(1);
|
|
select * from t1,t2;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# semijoin pullout
|
|
|
|
create table t3 (a int, b int);
|
|
create table t4 (a int primary key);
|
|
insert into t4 values(1),(2);
|
|
# we do it with prepared statements; by reading the expanded query we
|
|
# can see that
|
|
# - subquery->semijoin transformation is done at first EXECUTE
|
|
# - same for semijoin table pullout
|
|
# - both are reused by the second EXECUTE (where expanded_query is a
|
|
# pure join)
|
|
prepare stmt from 'select * from t3 where (a,a,b) in (select * from t1,t2,t4)';
|
|
select trace from information_schema.OPTIMIZER_TRACE;
|
|
execute stmt;
|
|
select trace from information_schema.OPTIMIZER_TRACE;
|
|
execute stmt;
|
|
select trace from information_schema.OPTIMIZER_TRACE;
|
|
DROP TABLE t1,t2,t3,t4;
|
|
|
|
# Trig_cond printing
|
|
|
|
create table t1(a int);
|
|
insert into t1 values(1),(1);
|
|
create table t2(a int);
|
|
insert into t2 values(1),(1);
|
|
# guarded pushed down conds for WHERE and ON in LEFT JOIN
|
|
select * from t1 left join t2 on t2.a=500 where t2.a is NULL;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
drop table t1,t2;
|
|
# guarded added conds for IN->EXISTS:
|
|
create table t1(a int, b int);
|
|
insert into t1 values(1,NULL),(NULL,2);
|
|
create table t2(c int, d int);
|
|
insert into t2 values(1,1),(2,2);
|
|
select * from t1 where (t1.a,t1.b) not in (select c,d from t2 where c>0);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# HAVING
|
|
select t1.a,avg(t2.c) as moyenne from t1, t2 where t2.c>-1
|
|
group by t1.a having moyenne<>0;
|
|
--replace_regex /("sort_buffer_size":) [0-9]+/\1 "NNN"/
|
|
select trace from information_schema.OPTIMIZER_TRACE;
|
|
# impossible HAVING
|
|
select t1.a,avg(t2.c) as moyenne from t1, t2 where t2.c>-1
|
|
group by t1.a having 4=5;
|
|
select trace from information_schema.OPTIMIZER_TRACE;
|
|
drop table t1,t2;
|
|
|
|
# HAVING
|
|
|
|
|
|
# test non-SELECT statements
|
|
|
|
update t6 set d=5 where d is NULL;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
delete from t6 where d=5;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
insert into t6 values(6),(7),(8);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
insert into t6 select * from t6 where d>7;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
update t5, t6 set t6.d=t6.d+t5.c+4-t5.c-4 where d>7000;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
delete t6 from t5, t6 where d>7000;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# Test optimizer_trace_offset/limit for consecutive
|
|
# non-related statements (as opposed to "for sub-statements"
|
|
# which is tested further below).
|
|
set optimizer_trace_offset=2,optimizer_trace_limit=2;
|
|
# should be empty
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
select 1;
|
|
select 2;
|
|
select 3;
|
|
select 4;
|
|
select 5;
|
|
# In normal mode, each SELECT is a standalone statement and generates
|
|
# one trace: so 3rd and 4th trace means 3rd and 4th SELECT.
|
|
# In ps-protocol mode, each SELECT is two statements: PREPARE and
|
|
# EXECUTE; each of the two creates one trace; so 3rd and 4th trace
|
|
# means 2nd SELECT (preparation) and 2nd SELECT again (execution).
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
set optimizer_trace_offset=-2,optimizer_trace_limit=2;
|
|
# should be empty
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
select 1;
|
|
select 2;
|
|
select 3;
|
|
select 4;
|
|
select 5;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
set optimizer_trace_offset=default,optimizer_trace_limit=default;
|
|
# should be empty
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
# For stored functions, stored procedures, triggers, with
|
|
# offset=-1,limit=1, what we see in the trace is the trace of the last
|
|
# statement (i.e. last call to mysql_execute_command()). Thus:
|
|
# - for a call to a stored procedure, we will see only the last
|
|
# statement of this procedure
|
|
# - for a call to a trigger, we will see only the last statement of
|
|
# this trigger, and not the caller.
|
|
# etc.
|
|
# If the user wants to see more, 'offset' should be adjusted.
|
|
|
|
# Stored functions
|
|
|
|
create table t1 (
|
|
id char(16) not null default '',
|
|
data int not null
|
|
) charset utf8mb4;
|
|
create table t2 (
|
|
s char(16),
|
|
i int,
|
|
d double
|
|
) charset utf8mb4;
|
|
delimiter |;
|
|
insert into t1 values ("a", 1), ("b", 2) |
|
|
insert into t2 values ("a", 1, 1.0), ("b", 2, 2.0), ("c", 3, 3.0), ("d", 4, 4.0) |
|
|
create function f1() returns int
|
|
begin
|
|
declare ret int;
|
|
insert into t1 values("z",0);
|
|
delete from t1 where id="z";
|
|
select sum(data) into ret from t1;
|
|
return ret;
|
|
end|
|
|
select f1()|
|
|
# Here we will see the trace of RETURN.
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
select s, f1() from t2 order by s desc|
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
select * from t6 where d in (select f1() from t2 where s="c")|
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
# Want to see the top and invoked sub-statements; this means 11 traces:
|
|
# 1 top statement + two executions of f1() (there is one
|
|
# execution inside the range optimizer and one "normal" execution);
|
|
# in the stored function we have traces: DECLARE (1 trace), 3 DMLs
|
|
# and RETURN (1 trace). 1+2*(1+3+1)=11.
|
|
# In ps-protocol mode, we have those 11, plus one for PREPARE of the
|
|
# top SELECT.
|
|
# We ask for a larger number (60) and will check how many we got.
|
|
# Note that when semijoin features are disabled, the subquery is
|
|
# treated differently: it is executed, so the order and amount of
|
|
# executions of f1() becomes different, which changes the order of
|
|
# substatements in the trace.
|
|
set @old_opt_switch=@@optimizer_switch;
|
|
# Test was created when sj-mat-scan could not handle this query...
|
|
set optimizer_switch="materialization=off";
|
|
set optimizer_trace_offset=-60, optimizer_trace_limit=60|
|
|
select * from t6 where d in (select f1() from t2 where s="c")|
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
select count(*) from information_schema.OPTIMIZER_TRACE|
|
|
# Want to see the DELETE (invoked sub-statement):
|
|
set optimizer_trace_offset=3, optimizer_trace_limit=1|
|
|
select * from t6 where d in (select f1() from t2 where s="c")|
|
|
# In normal mode, we have traces for the top SELECT, then the
|
|
# function's INSERT then the function's DELETE, so DELETE is the
|
|
# third trace, which we see.
|
|
# In ps-protocol mode, we also have trace of PREPARE for the top
|
|
# SELECT, so we see one trace before the DELETE: the INSERT.
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
set @@optimizer_switch=@old_opt_switch;
|
|
|
|
# Stored procedures
|
|
create procedure p1(arg char(1) charset utf8mb4)
|
|
begin
|
|
declare res int;
|
|
select d into res from t6 where d in (select f1() from t2 where s=arg);
|
|
select d+1 into res from t6 where d=res+1;
|
|
end|
|
|
set @old_opt_switch=@@optimizer_switch;
|
|
# Test was created when sj-mat-scan could not handle this query...
|
|
set optimizer_switch="materialization=off";
|
|
set optimizer_trace_offset=0, optimizer_trace_limit=100;
|
|
call p1("c")|
|
|
# Regex to replace 'NAME_CONST(var_name,value)' with 'var_name'
|
|
# in the opt trace when the variables used are declared within
|
|
# procedures or passed as arguments and log-bin is enabled.
|
|
--replace_regex /[ ]NAME_CONST[(][\'](.*)[\'][,][^)]*[)]/\1/
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
set @@optimizer_switch=@old_opt_switch;
|
|
|
|
# Triggers
|
|
create trigger trg1 before insert on t2 for each row
|
|
begin
|
|
set new.s=f1();
|
|
end|
|
|
set optimizer_trace_offset=0, optimizer_trace_limit=100|
|
|
insert into t2 select d,100,200 from t6 where d is not null|
|
|
select * from information_schema.OPTIMIZER_TRACE|
|
|
select * from t2|
|
|
delimiter ;|
|
|
|
|
# PREPARE/EXECUTE/EXECUTE
|
|
prepare stmt from 'select count(*) from t1 where t1.data=?';
|
|
set @param="c";
|
|
set optimizer_trace_offset=0, optimizer_trace_limit=100;
|
|
execute stmt using @param;
|
|
select count(*) from information_schema.OPTIMIZER_TRACE;
|
|
select TRACE into @trace from information_schema.OPTIMIZER_TRACE;
|
|
select @trace;
|
|
# second EXECUTE should give same trace
|
|
set optimizer_trace_offset=0, optimizer_trace_limit=100;
|
|
execute stmt using @param;
|
|
select count(*) from information_schema.OPTIMIZER_TRACE;
|
|
select TRACE into @trace2 from information_schema.OPTIMIZER_TRACE;
|
|
select @trace=@trace2;
|
|
|
|
# enable/disable tracing in middle of procedure
|
|
drop procedure p1;
|
|
create temporary table optt like information_schema.OPTIMIZER_TRACE;
|
|
delimiter |;
|
|
create procedure p1(arg char(1) charset utf8mb4)
|
|
begin
|
|
declare res int;
|
|
set optimizer_trace="enabled=off";
|
|
# want to see all of SELECT below
|
|
set optimizer_trace_offset=0, optimizer_trace_limit=100;
|
|
set optimizer_trace="enabled=on";
|
|
select d into res from t6 where d in (select f1() from t2 where s=arg);
|
|
set optimizer_trace="enabled=off"; # and not more
|
|
insert into optt select * from information_schema.OPTIMIZER_TRACE;
|
|
set optimizer_trace_offset=default, optimizer_trace_limit=default;
|
|
select d+1 into res from t6 where d=res+1;
|
|
end|
|
|
call p1("c")|
|
|
# Regex to replace 'NAME_CONST(var_name,value)' with 'var_name'
|
|
# in the opt trace when the variables used are declared within
|
|
# procedures or passed as arguments and log-bin is enabled.
|
|
--replace_regex /[ ]NAME_CONST[(][\'](.*)[\'][,][^)]*[)]/\1/
|
|
select * from optt|
|
|
select @@optimizer_trace|
|
|
delimiter ;|
|
|
|
|
set optimizer_trace="enabled=on";
|
|
drop temporary table optt;
|
|
drop function f1;
|
|
drop procedure p1;
|
|
drop trigger trg1;
|
|
|
|
# Views
|
|
# merge-able
|
|
create view v1 as select * from t1 where id < "c";
|
|
explain select * from v1 where id="b";
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
# insert into view
|
|
insert into v1 values("z", 100);
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
delete from v1 where data=100;
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
drop view v1;
|
|
# not merge-able
|
|
create view v1 as select * from t1 where id < "c" limit 2;
|
|
explain select * from v1 where id="b";
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
drop view v1;
|
|
|
|
# test that DUMPFILE does no escaping of \n
|
|
# otherwise a JSON parser could not read
|
|
set end_markers_in_json=off;
|
|
select 1 union select 2;
|
|
--let $file=$MYSQLTEST_VARDIR/tmp/optimizer_trace.txt
|
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
|
--eval select TRACE into dumpfile '$file' from information_schema.OPTIMIZER_TRACE;
|
|
# it has been manually checked that this file's content is JSON-compliant
|
|
--cat_file $file
|
|
--remove_file $file
|
|
|
|
# Test for crashing bug
|
|
--error ER_WRONG_VALUE_FOR_VAR
|
|
set optimizer_switch='default,index_merge=on,index_merge=off,default';
|
|
select @@optimizer_switch=@old_opt_switch;
|
|
|
|
# Test for long query (1070 chars)
|
|
--disable_query_log
|
|
--disable_result_log
|
|
select "abc1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111def" as col;
|
|
--enable_result_log
|
|
--enable_query_log
|
|
select * from information_schema.OPTIMIZER_TRACE;
|
|
|
|
drop table t1,t2;
|
|
DROP TABLE t5,t6;
|
|
set optimizer_trace=default;
|