mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
MDEV-36092 New-style hint: [NO_]SPLIT_MATERIALIZED
Support for optimizer hints NO_SPLIT_MATERIALIZED and SPLIT_MATERIALIZED. These hints allow fine-grained control of the "lateral derived" optimization within a query. Introduces new overload of hint_table_state function which tells both a hint's value as well as whether it is present. This is useful to disambiguate cases that the other version of hint_table_state cannot, such as when a hint is forcing a behavior in the optimizer that it would not normally do and the corresponding optimizer switch is enabled.
This commit is contained in:
committed by
Dave Gosselin
parent
07d71fdcf8
commit
62a1f0d990
781
mysql-test/main/opt_hints_split_materialized.result
Normal file
781
mysql-test/main/opt_hints_split_materialized.result
Normal file
@@ -0,0 +1,781 @@
|
|||||||
|
#
|
||||||
|
# MDEV-36092 New-style hint: [NO_]SPLIT_MATERIALIZED
|
||||||
|
#
|
||||||
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
|
#
|
||||||
|
# case 1
|
||||||
|
#
|
||||||
|
create table t1 (
|
||||||
|
n1 int(10) not null,
|
||||||
|
n2 int(10) not null,
|
||||||
|
c1 char(1) not null,
|
||||||
|
key c1 (c1),
|
||||||
|
key n1_c1_n2 (n1,c1,n2)
|
||||||
|
) engine=innodb charset=latin1;
|
||||||
|
insert into t1 values (0, 2, 'a'), (1, 3, 'a');
|
||||||
|
insert into t1 select seq+1,seq+2,'c' from seq_1_to_1000;
|
||||||
|
analyze table t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status Engine-independent statistics collected
|
||||||
|
test.t1 analyze status OK
|
||||||
|
# default showing lateral derived optimization in use
|
||||||
|
explain
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
2 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# cases where hint disables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ no_split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
2 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
select /*+ no_split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# query having two subqueries, both of which are subject to LATERAL DERIVED optimization
|
||||||
|
# explain and result without hints
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# explain and result with first half of query disabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# explain and result with second half of query disabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# explain and result with both halves of query disabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# test opposite way, where hint enables the optimization instead of disabling it
|
||||||
|
set optimizer_switch='split_materialized=off';
|
||||||
|
# default showing lateral derived optimization not used
|
||||||
|
explain
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
2 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# cases where hint enables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
2 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
select /*+ split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# query having two subqueries, both of which are subject to LATERAL DERIVED optimization
|
||||||
|
# explain and result without hints
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# explain and result with first half of query enabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# explain and result with second half of query enabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 DERIVED t1 ref c1 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
# explain and result with both halves of query enabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
|
2 DERIVED t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
2 DERIVED <derived3> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
3 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
4 UNION t1 ref c1,n1_c1_n2 c1 1 const 2 Using index condition; Using where; Using temporary; Using filesort
|
||||||
|
4 UNION <derived5> ref key0 key0 8 test.t1.n1,test.t1.n2 1
|
||||||
|
5 LATERAL DERIVED t1 ref c1,n1_c1_n2 n1_c1_n2 4 test.t1.n1 1 Using where; Using index
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
n1
|
||||||
|
0
|
||||||
|
1
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
drop table t1;
|
||||||
|
#
|
||||||
|
# end case 1
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# case 2
|
||||||
|
#
|
||||||
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
|
create table t1(a int, b int);
|
||||||
|
insert into t1 select seq,seq from seq_1_to_5;
|
||||||
|
create table t2(a int, b int, key(a));
|
||||||
|
insert into t2
|
||||||
|
select a.seq,b.seq from seq_1_to_25 a, seq_1_to_2 b;
|
||||||
|
create table t3(a int, b int, key(a));
|
||||||
|
insert into t3
|
||||||
|
select a.seq,b.seq from seq_1_to_5 a, seq_1_to_3 b;
|
||||||
|
analyze table t1,t2,t3 persistent for all;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 analyze status Engine-independent statistics collected
|
||||||
|
test.t1 analyze status OK
|
||||||
|
test.t2 analyze status Engine-independent statistics collected
|
||||||
|
test.t2 analyze status Table is already up to date
|
||||||
|
test.t3 analyze status Engine-independent statistics collected
|
||||||
|
test.t3 analyze status Table is already up to date
|
||||||
|
create table t10 (
|
||||||
|
grp_id int,
|
||||||
|
col1 int,
|
||||||
|
key(grp_id)
|
||||||
|
);
|
||||||
|
insert into t10
|
||||||
|
select
|
||||||
|
a.seq,
|
||||||
|
b.seq
|
||||||
|
from
|
||||||
|
seq_1_to_100 a,
|
||||||
|
seq_1_to_100 b;
|
||||||
|
create table t11 (
|
||||||
|
col1 int,
|
||||||
|
col2 int
|
||||||
|
);
|
||||||
|
insert into t11
|
||||||
|
select a.seq, a.seq from seq_1_to_10 a;
|
||||||
|
analyze table t10,t11 persistent for all;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t10 analyze status Engine-independent statistics collected
|
||||||
|
test.t10 analyze status Table is already up to date
|
||||||
|
test.t11 analyze status Engine-independent statistics collected
|
||||||
|
test.t11 analyze status OK
|
||||||
|
create table t21 (pk int primary key);
|
||||||
|
insert into t21 values (1),(2),(3);
|
||||||
|
create table t22 (pk int primary key);
|
||||||
|
insert into t22 values (1),(2),(3);
|
||||||
|
# default showing lateral derived optimization in use
|
||||||
|
explain
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t21 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
|
||||||
|
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
|
||||||
|
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 5 test.t1.b 10 Using where
|
||||||
|
2 LATERAL DERIVED t22 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
|
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
|
||||||
|
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
pk a b a b a b grp_id count(*)
|
||||||
|
1 1 1 1 1 1 1 1 100
|
||||||
|
1 1 1 1 1 1 2 1 100
|
||||||
|
1 1 1 1 1 1 3 1 100
|
||||||
|
1 1 1 1 2 1 1 1 100
|
||||||
|
1 1 1 1 2 1 2 1 100
|
||||||
|
1 1 1 1 2 1 3 1 100
|
||||||
|
1 2 2 2 1 2 1 2 100
|
||||||
|
1 2 2 2 1 2 2 2 100
|
||||||
|
1 2 2 2 1 2 3 2 100
|
||||||
|
1 2 2 2 2 2 1 2 100
|
||||||
|
1 2 2 2 2 2 2 2 100
|
||||||
|
1 2 2 2 2 2 3 2 100
|
||||||
|
1 3 3 3 1 3 1 3 100
|
||||||
|
1 3 3 3 1 3 2 3 100
|
||||||
|
1 3 3 3 1 3 3 3 100
|
||||||
|
1 3 3 3 2 3 1 3 100
|
||||||
|
1 3 3 3 2 3 2 3 100
|
||||||
|
1 3 3 3 2 3 3 3 100
|
||||||
|
1 4 4 4 1 4 1 4 100
|
||||||
|
1 4 4 4 1 4 2 4 100
|
||||||
|
1 4 4 4 1 4 3 4 100
|
||||||
|
1 4 4 4 2 4 1 4 100
|
||||||
|
1 4 4 4 2 4 2 4 100
|
||||||
|
1 4 4 4 2 4 3 4 100
|
||||||
|
1 5 5 5 1 5 1 5 100
|
||||||
|
1 5 5 5 1 5 2 5 100
|
||||||
|
1 5 5 5 1 5 3 5 100
|
||||||
|
1 5 5 5 2 5 1 5 100
|
||||||
|
1 5 5 5 2 5 2 5 100
|
||||||
|
1 5 5 5 2 5 3 5 100
|
||||||
|
# cases where hint disables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ no_split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t21 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
|
||||||
|
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
|
||||||
|
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 5 test.t1.b 10 Using where
|
||||||
|
2 DERIVED t22 const PRIMARY PRIMARY 4 const 1 Using index; Using temporary; Using filesort
|
||||||
|
2 DERIVED t10 ALL NULL NULL NULL NULL 10000
|
||||||
|
2 DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
|
||||||
|
select /*+ no_split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
pk a b a b a b grp_id count(*)
|
||||||
|
1 1 1 1 1 1 1 1 100
|
||||||
|
1 1 1 1 1 1 2 1 100
|
||||||
|
1 1 1 1 1 1 3 1 100
|
||||||
|
1 1 1 1 2 1 1 1 100
|
||||||
|
1 1 1 1 2 1 2 1 100
|
||||||
|
1 1 1 1 2 1 3 1 100
|
||||||
|
1 2 2 2 1 2 1 2 100
|
||||||
|
1 2 2 2 1 2 2 2 100
|
||||||
|
1 2 2 2 1 2 3 2 100
|
||||||
|
1 2 2 2 2 2 1 2 100
|
||||||
|
1 2 2 2 2 2 2 2 100
|
||||||
|
1 2 2 2 2 2 3 2 100
|
||||||
|
1 3 3 3 1 3 1 3 100
|
||||||
|
1 3 3 3 1 3 2 3 100
|
||||||
|
1 3 3 3 1 3 3 3 100
|
||||||
|
1 3 3 3 2 3 1 3 100
|
||||||
|
1 3 3 3 2 3 2 3 100
|
||||||
|
1 3 3 3 2 3 3 3 100
|
||||||
|
1 4 4 4 1 4 1 4 100
|
||||||
|
1 4 4 4 1 4 2 4 100
|
||||||
|
1 4 4 4 1 4 3 4 100
|
||||||
|
1 4 4 4 2 4 1 4 100
|
||||||
|
1 4 4 4 2 4 2 4 100
|
||||||
|
1 4 4 4 2 4 3 4 100
|
||||||
|
1 5 5 5 1 5 1 5 100
|
||||||
|
1 5 5 5 1 5 2 5 100
|
||||||
|
1 5 5 5 1 5 3 5 100
|
||||||
|
1 5 5 5 2 5 1 5 100
|
||||||
|
1 5 5 5 2 5 2 5 100
|
||||||
|
1 5 5 5 2 5 3 5 100
|
||||||
|
# test opposite way, where hint enables the optimization instead of disabling it
|
||||||
|
set optimizer_switch='split_materialized=off';
|
||||||
|
# default showing lateral derived optimization not used
|
||||||
|
explain
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t21 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
|
||||||
|
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
|
||||||
|
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 5 test.t1.b 10 Using where
|
||||||
|
2 DERIVED t22 const PRIMARY PRIMARY 4 const 1 Using index; Using temporary; Using filesort
|
||||||
|
2 DERIVED t10 ALL NULL NULL NULL NULL 10000
|
||||||
|
2 DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
pk a b a b a b grp_id count(*)
|
||||||
|
1 1 1 1 1 1 1 1 100
|
||||||
|
1 1 1 1 1 1 2 1 100
|
||||||
|
1 1 1 1 1 1 3 1 100
|
||||||
|
1 1 1 1 2 1 1 1 100
|
||||||
|
1 1 1 1 2 1 2 1 100
|
||||||
|
1 1 1 1 2 1 3 1 100
|
||||||
|
1 2 2 2 1 2 1 2 100
|
||||||
|
1 2 2 2 1 2 2 2 100
|
||||||
|
1 2 2 2 1 2 3 2 100
|
||||||
|
1 2 2 2 2 2 1 2 100
|
||||||
|
1 2 2 2 2 2 2 2 100
|
||||||
|
1 2 2 2 2 2 3 2 100
|
||||||
|
1 3 3 3 1 3 1 3 100
|
||||||
|
1 3 3 3 1 3 2 3 100
|
||||||
|
1 3 3 3 1 3 3 3 100
|
||||||
|
1 3 3 3 2 3 1 3 100
|
||||||
|
1 3 3 3 2 3 2 3 100
|
||||||
|
1 3 3 3 2 3 3 3 100
|
||||||
|
1 4 4 4 1 4 1 4 100
|
||||||
|
1 4 4 4 1 4 2 4 100
|
||||||
|
1 4 4 4 1 4 3 4 100
|
||||||
|
1 4 4 4 2 4 1 4 100
|
||||||
|
1 4 4 4 2 4 2 4 100
|
||||||
|
1 4 4 4 2 4 3 4 100
|
||||||
|
1 5 5 5 1 5 1 5 100
|
||||||
|
1 5 5 5 1 5 2 5 100
|
||||||
|
1 5 5 5 1 5 3 5 100
|
||||||
|
1 5 5 5 2 5 1 5 100
|
||||||
|
1 5 5 5 2 5 2 5 100
|
||||||
|
1 5 5 5 2 5 3 5 100
|
||||||
|
# cases where hint enables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t21 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
|
||||||
|
1 PRIMARY t2 ref a a 5 test.t1.b 2 Using where
|
||||||
|
1 PRIMARY t3 ref a a 5 test.t1.b 3 Using where
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 5 test.t1.b 10 Using where
|
||||||
|
2 LATERAL DERIVED t22 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
|
2 LATERAL DERIVED t10 ref grp_id grp_id 5 test.t1.b 100
|
||||||
|
2 LATERAL DERIVED t11 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
|
||||||
|
select /*+ split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
pk a b a b a b grp_id count(*)
|
||||||
|
1 1 1 1 1 1 1 1 100
|
||||||
|
1 1 1 1 1 1 2 1 100
|
||||||
|
1 1 1 1 1 1 3 1 100
|
||||||
|
1 1 1 1 2 1 1 1 100
|
||||||
|
1 1 1 1 2 1 2 1 100
|
||||||
|
1 1 1 1 2 1 3 1 100
|
||||||
|
1 2 2 2 1 2 1 2 100
|
||||||
|
1 2 2 2 1 2 2 2 100
|
||||||
|
1 2 2 2 1 2 3 2 100
|
||||||
|
1 2 2 2 2 2 1 2 100
|
||||||
|
1 2 2 2 2 2 2 2 100
|
||||||
|
1 2 2 2 2 2 3 2 100
|
||||||
|
1 3 3 3 1 3 1 3 100
|
||||||
|
1 3 3 3 1 3 2 3 100
|
||||||
|
1 3 3 3 1 3 3 3 100
|
||||||
|
1 3 3 3 2 3 1 3 100
|
||||||
|
1 3 3 3 2 3 2 3 100
|
||||||
|
1 3 3 3 2 3 3 3 100
|
||||||
|
1 4 4 4 1 4 1 4 100
|
||||||
|
1 4 4 4 1 4 2 4 100
|
||||||
|
1 4 4 4 1 4 3 4 100
|
||||||
|
1 4 4 4 2 4 1 4 100
|
||||||
|
1 4 4 4 2 4 2 4 100
|
||||||
|
1 4 4 4 2 4 3 4 100
|
||||||
|
1 5 5 5 1 5 1 5 100
|
||||||
|
1 5 5 5 1 5 2 5 100
|
||||||
|
1 5 5 5 1 5 3 5 100
|
||||||
|
1 5 5 5 2 5 1 5 100
|
||||||
|
1 5 5 5 2 5 2 5 100
|
||||||
|
1 5 5 5 2 5 3 5 100
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
drop table t1, t2, t3, t10, t11, t21, t22;
|
||||||
|
#
|
||||||
|
# end case 2
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# case 3
|
||||||
|
#
|
||||||
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
|
create table t1 (a char(1)) engine=myisam;
|
||||||
|
insert into t1 values ('1'),('2');
|
||||||
|
create table t2 (b int, key(b)) engine=myisam;
|
||||||
|
alter table t2 disable keys;
|
||||||
|
insert into t2 values (1),(2),(3);
|
||||||
|
alter table t2 enable keys;
|
||||||
|
create table t3 (c int) engine=myisam;
|
||||||
|
insert into t3 (c) select seq from seq_1_to_101;
|
||||||
|
# default showing lateral derived optimization in use
|
||||||
|
explain
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 Using where
|
||||||
|
3 LATERAL DERIVED t2 ref b b 5 test.t1.a 1 Using where; Using index; Using temporary; Using filesort
|
||||||
|
4 SUBQUERY t3 ALL NULL NULL NULL NULL 101
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
a
|
||||||
|
# cases where hint disables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ no_split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 Using where
|
||||||
|
3 DERIVED t2 range NULL b 5 NULL 3 Using where; Using index for group-by
|
||||||
|
4 SUBQUERY t3 ALL NULL NULL NULL NULL 101
|
||||||
|
select /*+ no_split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
a
|
||||||
|
# test opposite way, where hint enables the optimization instead of disabling it
|
||||||
|
set optimizer_switch='split_materialized=off';
|
||||||
|
# default showing lateral derived optimization not used
|
||||||
|
explain
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 Using where
|
||||||
|
3 DERIVED t2 range NULL b 5 NULL 3 Using where; Using index for group-by
|
||||||
|
4 SUBQUERY t3 ALL NULL NULL NULL NULL 101
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
a
|
||||||
|
# cases where hint enables lateral derived optimization
|
||||||
|
explain select /*+ split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
|
||||||
|
1 PRIMARY <derived3> eq_ref distinct_key distinct_key 5 test.t1.a 1 Using where
|
||||||
|
3 LATERAL DERIVED t2 ref b b 5 test.t1.a 1 Using where; Using index; Using temporary; Using filesort
|
||||||
|
4 SUBQUERY t3 ALL NULL NULL NULL NULL 101
|
||||||
|
select /*+ split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
a
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
drop table t1, t2, t3;
|
||||||
|
#
|
||||||
|
# end case 3
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# case 4
|
||||||
|
#
|
||||||
|
create table one_k(a int);
|
||||||
|
insert into one_k select seq from seq_1_to_1000;
|
||||||
|
CREATE TABLE t1000 (
|
||||||
|
grp int(11) DEFAULT NULL,
|
||||||
|
val int(11) DEFAULT NULL,
|
||||||
|
KEY grp (grp)
|
||||||
|
);
|
||||||
|
insert into t1000 select A.seq, B.seq from seq_1_to_100 A, seq_1_to_10 B;
|
||||||
|
analyze table t1000;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1000 analyze status Engine-independent statistics collected
|
||||||
|
test.t1000 analyze status Table is already up to date
|
||||||
|
# force lateral derived when optimizer otherwise wouldn't use it
|
||||||
|
explain
|
||||||
|
select *
|
||||||
|
from
|
||||||
|
one_k T1, (select grp, count(*) from t1000 group by grp) TBL where TBL.grp=T1.a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY T1 ALL NULL NULL NULL NULL 1000 Using where
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 5 test.T1.a 10
|
||||||
|
2 DERIVED t1000 index grp grp 5 NULL 1000 Using index; Using temporary; Using filesort
|
||||||
|
explain
|
||||||
|
select /*+ SPLIT_MATERIALIZED(TBL) */ *
|
||||||
|
from
|
||||||
|
one_k T1, (select grp, count(*) from t1000 group by grp) TBL where TBL.grp=T1.a;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY T1 ALL NULL NULL NULL NULL 1000 Using where
|
||||||
|
1 PRIMARY <derived2> ref key0 key0 5 test.T1.a 1
|
||||||
|
2 LATERAL DERIVED t1000 ref grp grp 5 test.T1.a 10 Using index
|
||||||
|
drop table one_k, t1000;
|
||||||
|
#
|
||||||
|
# end case 4
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# End 12.1 tests
|
||||||
|
#
|
525
mysql-test/main/opt_hints_split_materialized.test
Normal file
525
mysql-test/main/opt_hints_split_materialized.test
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
--echo #
|
||||||
|
--echo # MDEV-36092 New-style hint: [NO_]SPLIT_MATERIALIZED
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_sequence.inc
|
||||||
|
|
||||||
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # case 1
|
||||||
|
--echo #
|
||||||
|
create table t1 (
|
||||||
|
n1 int(10) not null,
|
||||||
|
n2 int(10) not null,
|
||||||
|
c1 char(1) not null,
|
||||||
|
key c1 (c1),
|
||||||
|
key n1_c1_n2 (n1,c1,n2)
|
||||||
|
) engine=innodb charset=latin1;
|
||||||
|
insert into t1 values (0, 2, 'a'), (1, 3, 'a');
|
||||||
|
insert into t1 select seq+1,seq+2,'c' from seq_1_to_1000;
|
||||||
|
|
||||||
|
analyze table t1;
|
||||||
|
|
||||||
|
--echo # default showing lateral derived optimization in use
|
||||||
|
explain
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
--echo # cases where hint disables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ no_split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
select /*+ no_split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
--echo # query having two subqueries, both of which are subject to LATERAL DERIVED optimization
|
||||||
|
--echo # explain and result without hints
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
|
||||||
|
--echo # explain and result with first half of query disabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
|
||||||
|
--echo # explain and result with second half of query disabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
--echo # explain and result with both halves of query disabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ NO_SPLIT_MATERIALIZED(t@qb1) NO_SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
--echo # test opposite way, where hint enables the optimization instead of disabling it
|
||||||
|
set optimizer_switch='split_materialized=off';
|
||||||
|
|
||||||
|
--echo # default showing lateral derived optimization not used
|
||||||
|
explain
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
--echo # cases where hint enables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
select /*+ split_materialized(t) */ t1.n1 from t1,
|
||||||
|
(select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1;
|
||||||
|
|
||||||
|
--echo # query having two subqueries, both of which are subject to LATERAL DERIVED optimization
|
||||||
|
--echo # explain and result without hints
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select * from cte;
|
||||||
|
|
||||||
|
--echo # explain and result with first half of query enabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) */ * from cte;
|
||||||
|
|
||||||
|
--echo # explain and result with second half of query enabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
--echo # explain and result with both halves of query enabling the optimization
|
||||||
|
explain
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
with cte as (
|
||||||
|
select /*+ QB_NAME(qb1) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1
|
||||||
|
union
|
||||||
|
select /*+ QB_NAME(qb2) */ t1.n1 from t1, (select n1, n2 from t1 where c1 = 'a' group by n1) as t
|
||||||
|
where t.n1 = t1.n1 and t.n2 = t1.n2 and c1 = 'a' group by n1)
|
||||||
|
select /*+ SPLIT_MATERIALIZED(t@qb1) SPLIT_MATERIALIZED(t@qb2) */ * from cte;
|
||||||
|
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
drop table t1;
|
||||||
|
--echo #
|
||||||
|
--echo # end case 1
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # case 2
|
||||||
|
--echo #
|
||||||
|
# 5 values
|
||||||
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
|
|
||||||
|
create table t1(a int, b int);
|
||||||
|
insert into t1 select seq,seq from seq_1_to_5;
|
||||||
|
|
||||||
|
# 5 value groups of size 2 each
|
||||||
|
create table t2(a int, b int, key(a));
|
||||||
|
insert into t2
|
||||||
|
select a.seq,b.seq from seq_1_to_25 a, seq_1_to_2 b;
|
||||||
|
|
||||||
|
# 5 value groups of size 3 each
|
||||||
|
create table t3(a int, b int, key(a));
|
||||||
|
insert into t3
|
||||||
|
select a.seq,b.seq from seq_1_to_5 a, seq_1_to_3 b;
|
||||||
|
|
||||||
|
analyze table t1,t2,t3 persistent for all;
|
||||||
|
|
||||||
|
create table t10 (
|
||||||
|
grp_id int,
|
||||||
|
col1 int,
|
||||||
|
key(grp_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
# 100 groups of 100 values each
|
||||||
|
insert into t10
|
||||||
|
select
|
||||||
|
a.seq,
|
||||||
|
b.seq
|
||||||
|
from
|
||||||
|
seq_1_to_100 a,
|
||||||
|
seq_1_to_100 b;
|
||||||
|
|
||||||
|
# and x10 multiplier
|
||||||
|
|
||||||
|
create table t11 (
|
||||||
|
col1 int,
|
||||||
|
col2 int
|
||||||
|
);
|
||||||
|
insert into t11
|
||||||
|
select a.seq, a.seq from seq_1_to_10 a;
|
||||||
|
|
||||||
|
analyze table t10,t11 persistent for all;
|
||||||
|
|
||||||
|
create table t21 (pk int primary key);
|
||||||
|
insert into t21 values (1),(2),(3);
|
||||||
|
|
||||||
|
create table t22 (pk int primary key);
|
||||||
|
insert into t22 values (1),(2),(3);
|
||||||
|
|
||||||
|
--echo # default showing lateral derived optimization in use
|
||||||
|
explain
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
--echo # cases where hint disables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ no_split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
select /*+ no_split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
--echo # test opposite way, where hint enables the optimization instead of disabling it
|
||||||
|
set optimizer_switch='split_materialized=off';
|
||||||
|
|
||||||
|
--echo # default showing lateral derived optimization not used
|
||||||
|
explain
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
select * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
--echo # cases where hint enables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
select /*+ split_materialized(t) */ * from
|
||||||
|
t21,
|
||||||
|
(
|
||||||
|
(t1 left join t2 on t2.a=t1.b)
|
||||||
|
left join t3 on t3.a=t1.b
|
||||||
|
) left join (select grp_id, count(*)
|
||||||
|
from
|
||||||
|
t22 join t10 left join t11 on t11.col1=t10.col1
|
||||||
|
where
|
||||||
|
t22.pk=1
|
||||||
|
group by grp_id) t on t.grp_id=t1.b
|
||||||
|
where
|
||||||
|
t21.pk=1;
|
||||||
|
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
drop table t1, t2, t3, t10, t11, t21, t22;
|
||||||
|
--echo #
|
||||||
|
--echo # end case 2
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # case 3
|
||||||
|
--echo #
|
||||||
|
set @save_optimizer_switch=@@optimizer_switch;
|
||||||
|
|
||||||
|
create table t1 (a char(1)) engine=myisam;
|
||||||
|
insert into t1 values ('1'),('2');
|
||||||
|
create table t2 (b int, key(b)) engine=myisam;
|
||||||
|
alter table t2 disable keys;
|
||||||
|
insert into t2 values (1),(2),(3);
|
||||||
|
alter table t2 enable keys;
|
||||||
|
create table t3 (c int) engine=myisam;
|
||||||
|
insert into t3 (c) select seq from seq_1_to_101;
|
||||||
|
|
||||||
|
--echo # default showing lateral derived optimization in use
|
||||||
|
explain
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
--echo # cases where hint disables lateral derived optimization
|
||||||
|
explain
|
||||||
|
select /*+ no_split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
select /*+ no_split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
--echo # test opposite way, where hint enables the optimization instead of disabling it
|
||||||
|
set optimizer_switch='split_materialized=off';
|
||||||
|
|
||||||
|
--echo # default showing lateral derived optimization not used
|
||||||
|
explain
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
select * from t1 where t1.a in (
|
||||||
|
select b from (
|
||||||
|
select t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
--echo # cases where hint enables lateral derived optimization
|
||||||
|
explain select /*+ split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
select /*+ split_materialized(@qb1 sq) */ * from t1 where t1.a in (
|
||||||
|
select /*+ qb_name(qb1) */ b from (
|
||||||
|
select /*+ qb_name(qb2) */ t2.b from t2 where not exists (
|
||||||
|
select 1 from t3
|
||||||
|
) group by b
|
||||||
|
) sq
|
||||||
|
);
|
||||||
|
|
||||||
|
set optimizer_switch=@save_optimizer_switch;
|
||||||
|
drop table t1, t2, t3;
|
||||||
|
--echo #
|
||||||
|
--echo # end case 3
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # case 4
|
||||||
|
--echo #
|
||||||
|
create table one_k(a int);
|
||||||
|
insert into one_k select seq from seq_1_to_1000;
|
||||||
|
|
||||||
|
CREATE TABLE t1000 (
|
||||||
|
grp int(11) DEFAULT NULL,
|
||||||
|
val int(11) DEFAULT NULL,
|
||||||
|
KEY grp (grp)
|
||||||
|
);
|
||||||
|
|
||||||
|
insert into t1000 select A.seq, B.seq from seq_1_to_100 A, seq_1_to_10 B;
|
||||||
|
analyze table t1000;
|
||||||
|
|
||||||
|
--echo # force lateral derived when optimizer otherwise wouldn't use it
|
||||||
|
explain
|
||||||
|
select *
|
||||||
|
from
|
||||||
|
one_k T1, (select grp, count(*) from t1000 group by grp) TBL where TBL.grp=T1.a;
|
||||||
|
|
||||||
|
explain
|
||||||
|
select /*+ SPLIT_MATERIALIZED(TBL) */ *
|
||||||
|
from
|
||||||
|
one_k T1, (select grp, count(*) from t1000 group by grp) TBL where TBL.grp=T1.a;
|
||||||
|
|
||||||
|
drop table one_k, t1000;
|
||||||
|
--echo #
|
||||||
|
--echo # end case 4
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End 12.1 tests
|
||||||
|
--echo #
|
@@ -47,6 +47,7 @@ struct st_opt_hint_info opt_hint_info[]=
|
|||||||
{{STRING_WITH_LEN("JOIN_FIXED_ORDER")}, false, true, false},
|
{{STRING_WITH_LEN("JOIN_FIXED_ORDER")}, false, true, false},
|
||||||
{{STRING_WITH_LEN("DERIVED_CONDITION_PUSHDOWN")}, false, false, false},
|
{{STRING_WITH_LEN("DERIVED_CONDITION_PUSHDOWN")}, false, false, false},
|
||||||
{{STRING_WITH_LEN("MERGE")}, false, false, false},
|
{{STRING_WITH_LEN("MERGE")}, false, false, false},
|
||||||
|
{{STRING_WITH_LEN("SPLIT_MATERIALIZED")}, false, false, false},
|
||||||
{null_clex_str, 0, 0, 0}
|
{null_clex_str, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -608,6 +609,54 @@ static bool get_hint_state(Opt_hints *hint,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
In addition to indicating the state of a hint, also indicates
|
||||||
|
if the hint is present or not. Serves to disambiguate cases
|
||||||
|
that the other version of hint_table_state cannot, such as
|
||||||
|
when a hint is forcing a behavior in the optimizer that it
|
||||||
|
would not normally do and the corresponding optimizer switch
|
||||||
|
is enabled.
|
||||||
|
|
||||||
|
@param thd Current thread connection state
|
||||||
|
@param table_list Table having the hint
|
||||||
|
@param type_arg The hint kind in question
|
||||||
|
|
||||||
|
@return appropriate value from hint_state enumeration
|
||||||
|
indicating hint enabled/disabled (if present) or
|
||||||
|
if the hint was not present.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hint_state hint_table_state(const THD *thd,
|
||||||
|
const TABLE_LIST *table_list,
|
||||||
|
opt_hints_enum type_arg)
|
||||||
|
{
|
||||||
|
if (!table_list->opt_hints_qb)
|
||||||
|
return hint_state::NOT_PRESENT;
|
||||||
|
|
||||||
|
DBUG_ASSERT(!opt_hint_info[type_arg].has_arguments);
|
||||||
|
|
||||||
|
Opt_hints *hint= table_list->opt_hints_table;
|
||||||
|
Opt_hints *parent_hint= table_list->opt_hints_qb;
|
||||||
|
|
||||||
|
if (hint && hint->is_specified(type_arg))
|
||||||
|
{
|
||||||
|
const bool hint_value= hint->get_switch(type_arg);
|
||||||
|
return hint_value ? hint_state::ENABLED :
|
||||||
|
hint_state::DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_hint_info[type_arg].check_upper_lvl &&
|
||||||
|
parent_hint->is_specified(type_arg))
|
||||||
|
{
|
||||||
|
const bool hint_value= parent_hint->get_switch(type_arg);
|
||||||
|
return hint_value ? hint_state::ENABLED :
|
||||||
|
hint_state::DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hint_state::NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@brief
|
@brief
|
||||||
Check whether a given optimization is enabled for table.keyno.
|
Check whether a given optimization is enabled for table.keyno.
|
||||||
|
@@ -659,6 +659,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum class hint_state
|
||||||
|
{
|
||||||
|
NOT_PRESENT, // Hint is not specified
|
||||||
|
ENABLED, // Hint is specified as enabled
|
||||||
|
DISABLED // Hint is specified as disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns key hint value if hint is specified, returns
|
Returns key hint value if hint is specified, returns
|
||||||
optimizer switch value if hint is not specified.
|
optimizer switch value if hint is not specified.
|
||||||
@@ -706,6 +714,14 @@ bool hint_table_state(const THD *thd, const TABLE_LIST *table_list,
|
|||||||
bool hint_table_state(const THD *thd, const TABLE *table,
|
bool hint_table_state(const THD *thd, const TABLE *table,
|
||||||
opt_hints_enum type_arg, bool fallback_value);
|
opt_hints_enum type_arg, bool fallback_value);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Similar to above but returns hint_state enum
|
||||||
|
*/
|
||||||
|
hint_state hint_table_state(const THD *thd,
|
||||||
|
const TABLE_LIST *table_list,
|
||||||
|
opt_hints_enum type_arg);
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
const char *dbug_print_hints(Opt_hints_qb *hint);
|
const char *dbug_print_hints(Opt_hints_qb *hint);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -134,11 +134,15 @@ Optimizer_hint_tokenizer::find_keyword(const LEX_CSTRING &str)
|
|||||||
case 18:
|
case 18:
|
||||||
if ("MAX_EXECUTION_TIME"_Lex_ident_column.streq(str))
|
if ("MAX_EXECUTION_TIME"_Lex_ident_column.streq(str))
|
||||||
return TokenID::keyword_MAX_EXECUTION_TIME;
|
return TokenID::keyword_MAX_EXECUTION_TIME;
|
||||||
|
if ("SPLIT_MATERIALIZED"_Lex_ident_column.streq(str))
|
||||||
|
return TokenID::keyword_SPLIT_MATERIALIZED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 21:
|
case 21:
|
||||||
if ("NO_RANGE_OPTIMIZATION"_Lex_ident_column.streq(str))
|
if ("NO_RANGE_OPTIMIZATION"_Lex_ident_column.streq(str))
|
||||||
return TokenID::keyword_NO_RANGE_OPTIMIZATION;
|
return TokenID::keyword_NO_RANGE_OPTIMIZATION;
|
||||||
|
if ("NO_SPLIT_MATERIALIZED"_Lex_ident_column.streq(str))
|
||||||
|
return TokenID::keyword_NO_SPLIT_MATERIALIZED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 26:
|
case 26:
|
||||||
@@ -357,6 +361,14 @@ bool Parser::Table_level_hint::resolve(Parse_context *pc) const
|
|||||||
hint_type= MERGE_HINT_ENUM;
|
hint_type= MERGE_HINT_ENUM;
|
||||||
hint_state= false;
|
hint_state= false;
|
||||||
break;
|
break;
|
||||||
|
case TokenID::keyword_SPLIT_MATERIALIZED:
|
||||||
|
hint_type= SPLIT_MATERIALIZED_HINT_ENUM;
|
||||||
|
hint_state= true;
|
||||||
|
break;
|
||||||
|
case TokenID::keyword_NO_SPLIT_MATERIALIZED:
|
||||||
|
hint_type= SPLIT_MATERIALIZED_HINT_ENUM;
|
||||||
|
hint_state= false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return true;
|
return true;
|
||||||
|
@@ -50,6 +50,7 @@ enum opt_hints_enum
|
|||||||
JOIN_FIXED_ORDER_HINT_ENUM,
|
JOIN_FIXED_ORDER_HINT_ENUM,
|
||||||
DERIVED_CONDITION_PUSHDOWN_HINT_ENUM,
|
DERIVED_CONDITION_PUSHDOWN_HINT_ENUM,
|
||||||
MERGE_HINT_ENUM,
|
MERGE_HINT_ENUM,
|
||||||
|
SPLIT_MATERIALIZED_HINT_ENUM,
|
||||||
MAX_HINT_ENUM // This one must be the last in the list
|
MAX_HINT_ENUM // This one must be the last in the list
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +119,9 @@ public:
|
|||||||
keyword_DERIVED_CONDITION_PUSHDOWN,
|
keyword_DERIVED_CONDITION_PUSHDOWN,
|
||||||
keyword_NO_DERIVED_CONDITION_PUSHDOWN,
|
keyword_NO_DERIVED_CONDITION_PUSHDOWN,
|
||||||
keyword_MERGE,
|
keyword_MERGE,
|
||||||
keyword_NO_MERGE
|
keyword_NO_MERGE,
|
||||||
|
keyword_SPLIT_MATERIALIZED,
|
||||||
|
keyword_NO_SPLIT_MATERIALIZED
|
||||||
};
|
};
|
||||||
|
|
||||||
class Token: public Lex_cstring
|
class Token: public Lex_cstring
|
||||||
@@ -373,7 +376,9 @@ private:
|
|||||||
id == TokenID::keyword_DERIVED_CONDITION_PUSHDOWN ||
|
id == TokenID::keyword_DERIVED_CONDITION_PUSHDOWN ||
|
||||||
id == TokenID::keyword_NO_DERIVED_CONDITION_PUSHDOWN ||
|
id == TokenID::keyword_NO_DERIVED_CONDITION_PUSHDOWN ||
|
||||||
id == TokenID::keyword_MERGE ||
|
id == TokenID::keyword_MERGE ||
|
||||||
id == TokenID::keyword_NO_MERGE;
|
id == TokenID::keyword_NO_MERGE ||
|
||||||
|
id == TokenID::keyword_SPLIT_MATERIALIZED ||
|
||||||
|
id == TokenID::keyword_NO_SPLIT_MATERIALIZED;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class Table_level_hint_type: public TokenChoice<Parser,
|
class Table_level_hint_type: public TokenChoice<Parser,
|
||||||
|
@@ -228,6 +228,7 @@
|
|||||||
|
|
||||||
#include "mariadb.h"
|
#include "mariadb.h"
|
||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
|
#include "opt_hints.h"
|
||||||
#include "opt_trace.h"
|
#include "opt_trace.h"
|
||||||
#include "optimizer_defaults.h"
|
#include "optimizer_defaults.h"
|
||||||
|
|
||||||
@@ -292,6 +293,8 @@ public:
|
|||||||
/* Cardinality of T when nothing is pushed */
|
/* Cardinality of T when nothing is pushed */
|
||||||
double unsplit_card;
|
double unsplit_card;
|
||||||
double last_refills;
|
double last_refills;
|
||||||
|
/* True when SPLIT_MATERIALIZED hint present and forces this split. */
|
||||||
|
bool hint_forced_split{false};
|
||||||
|
|
||||||
SplM_plan_info *find_plan(TABLE *table, uint key, uint parts);
|
SplM_plan_info *find_plan(TABLE *table, uint key, uint parts);
|
||||||
};
|
};
|
||||||
@@ -299,7 +302,7 @@ public:
|
|||||||
|
|
||||||
void TABLE::set_spl_opt_info(SplM_opt_info *spl_info)
|
void TABLE::set_spl_opt_info(SplM_opt_info *spl_info)
|
||||||
{
|
{
|
||||||
if (spl_info)
|
DBUG_ASSERT(spl_info);
|
||||||
spl_info->join->spl_opt_info= spl_info;
|
spl_info->join->spl_opt_info= spl_info;
|
||||||
spl_opt_info= spl_info;
|
spl_opt_info= spl_info;
|
||||||
}
|
}
|
||||||
@@ -320,6 +323,40 @@ double TABLE::get_materialization_cost()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns true if split materialization is permitted for the
|
||||||
|
derived table passed in argument 'derived'.
|
||||||
|
|
||||||
|
@param thd The connection state for the current thread.
|
||||||
|
@param derived The candidate derived table for split materialization.
|
||||||
|
@param hint [OUT] One of the values from the hint_state enumeration
|
||||||
|
found in opt_hints.h
|
||||||
|
@return true if split materialization allowed, either by hint
|
||||||
|
or by optimizer option. The hint takes precedence.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool is_split_materialized_allowed(THD *thd,
|
||||||
|
const TABLE_LIST *derived,
|
||||||
|
hint_state *hint)
|
||||||
|
{
|
||||||
|
if (!derived)
|
||||||
|
{
|
||||||
|
*hint= hint_state::DISABLED; // there is no derived table to hint on
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*hint= hint_table_state(thd,
|
||||||
|
derived,
|
||||||
|
SPLIT_MATERIALIZED_HINT_ENUM);
|
||||||
|
|
||||||
|
const bool opt_flag= optimizer_flag(thd, OPTIMIZER_SWITCH_SPLIT_MATERIALIZED);
|
||||||
|
const bool allow_split= (*hint == hint_state::ENABLED ||
|
||||||
|
(*hint == hint_state::NOT_PRESENT && opt_flag));
|
||||||
|
|
||||||
|
return allow_split;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This structure is auxiliary and used only in the function that follows it */
|
/* This structure is auxiliary and used only in the function that follows it */
|
||||||
struct SplM_field_ext_info: public SplM_field_info
|
struct SplM_field_ext_info: public SplM_field_info
|
||||||
{
|
{
|
||||||
@@ -330,7 +367,8 @@ struct SplM_field_ext_info: public SplM_field_info
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
@brief
|
@brief
|
||||||
Check whether this join is one for potentially splittable materialized table
|
Check whether this join is one for potentially splittable materialized
|
||||||
|
table
|
||||||
|
|
||||||
@details
|
@details
|
||||||
The function checks whether this join is for select that specifies
|
The function checks whether this join is for select that specifies
|
||||||
@@ -339,7 +377,8 @@ struct SplM_field_ext_info: public SplM_field_info
|
|||||||
of the TABLE structure for T.
|
of the TABLE structure for T.
|
||||||
|
|
||||||
The function returns a positive answer if the following holds:
|
The function returns a positive answer if the following holds:
|
||||||
1. the optimizer switch 'split_materialized' is set 'on'
|
1. The is_split_materialized_allowed() function indicates that split
|
||||||
|
materialization is permitted for the derived table.
|
||||||
2. the select owning this join specifies a materialized derived/view/cte T
|
2. the select owning this join specifies a materialized derived/view/cte T
|
||||||
3. this is the only select in the specification of T
|
3. this is the only select in the specification of T
|
||||||
4. condition pushdown is not prohibited into T
|
4. condition pushdown is not prohibited into T
|
||||||
@@ -367,8 +406,10 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
ORDER *partition_list= 0;
|
ORDER *partition_list= 0;
|
||||||
st_select_lex_unit *unit= select_lex->master_unit();
|
st_select_lex_unit *unit= select_lex->master_unit();
|
||||||
TABLE_LIST *derived= unit->derived;
|
TABLE_LIST *derived= unit->derived;
|
||||||
if (!(optimizer_flag(thd, OPTIMIZER_SWITCH_SPLIT_MATERIALIZED)) || // !(1)
|
|
||||||
!(derived && derived->is_materialized_derived()) || // !(2)
|
hint_state hint;
|
||||||
|
if (!is_split_materialized_allowed(thd, derived, &hint) || // !(1)
|
||||||
|
!derived->is_materialized_derived() || // !(2)
|
||||||
(unit->first_select()->next_select()) || // !(3)
|
(unit->first_select()->next_select()) || // !(3)
|
||||||
(derived->prohibit_cond_pushdown) || // !(4)
|
(derived->prohibit_cond_pushdown) || // !(4)
|
||||||
(derived->is_recursive_with_table()) || // !(5)
|
(derived->is_recursive_with_table()) || // !(5)
|
||||||
@@ -519,6 +560,7 @@ bool JOIN::check_for_splittable_materialized()
|
|||||||
spl_opt_info->tables_usable_for_splitting= 0;
|
spl_opt_info->tables_usable_for_splitting= 0;
|
||||||
spl_opt_info->spl_field_cnt= spl_field_cnt;
|
spl_opt_info->spl_field_cnt= spl_field_cnt;
|
||||||
spl_opt_info->spl_fields= spl_field;
|
spl_opt_info->spl_fields= spl_field;
|
||||||
|
spl_opt_info->hint_forced_split= (hint == hint_state::ENABLED);
|
||||||
|
|
||||||
{
|
{
|
||||||
Json_writer_array trace_range(thd, "split_candidates");
|
Json_writer_array trace_range(thd, "split_candidates");
|
||||||
@@ -1130,8 +1172,8 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx,
|
|||||||
spl_plan->cost= (join->best_positions[join->table_count-1].read_time +
|
spl_plan->cost= (join->best_positions[join->table_count-1].read_time +
|
||||||
oper_cost);
|
oper_cost);
|
||||||
|
|
||||||
chosen= (refills * spl_plan->cost + COST_EPS <
|
chosen= ((refills * spl_plan->cost + COST_EPS <
|
||||||
spl_opt_info->unsplit_cost);
|
spl_opt_info->unsplit_cost) || spl_opt_info->hint_forced_split);
|
||||||
|
|
||||||
if (unlikely(thd->trace_started()))
|
if (unlikely(thd->trace_started()))
|
||||||
{
|
{
|
||||||
@@ -1149,6 +1191,9 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx,
|
|||||||
add("refills", refills).
|
add("refills", refills).
|
||||||
add("total_splitting_cost", refills * spl_plan->cost).
|
add("total_splitting_cost", refills * spl_plan->cost).
|
||||||
add("chosen", chosen);
|
add("chosen", chosen);
|
||||||
|
|
||||||
|
if (spl_opt_info->hint_forced_split)
|
||||||
|
find_trace.add("forced_by_hint", true);
|
||||||
}
|
}
|
||||||
memcpy((char *) spl_plan->best_positions,
|
memcpy((char *) spl_plan->best_positions,
|
||||||
(char *) join->best_positions,
|
(char *) join->best_positions,
|
||||||
@@ -1160,8 +1205,11 @@ SplM_plan_info * JOIN_TAB::choose_best_splitting(uint idx,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
trace_obj.add("cached_plan_found", 1);
|
trace_obj.add("cached_plan_found", 1);
|
||||||
chosen= (refills * spl_plan->cost + COST_EPS <
|
if (spl_opt_info->hint_forced_split)
|
||||||
spl_opt_info->unsplit_cost);
|
trace_obj.add("forced_by_hint", true);
|
||||||
|
|
||||||
|
chosen= ((refills * spl_plan->cost + COST_EPS <
|
||||||
|
spl_opt_info->unsplit_cost) || spl_opt_info->hint_forced_split);
|
||||||
already_printed= 0;
|
already_printed= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2971,6 +2971,11 @@ struct TABLE_LIST
|
|||||||
/* I_S: Flags to open_table (e.g. OPEN_TABLE_ONLY or OPEN_VIEW_ONLY) */
|
/* I_S: Flags to open_table (e.g. OPEN_TABLE_ONLY or OPEN_VIEW_ONLY) */
|
||||||
uint i_s_requested_object;
|
uint i_s_requested_object;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The [NO_]SPLIT_MATERIALIZED hint will not override this because
|
||||||
|
this is in place for correctness (see Item_func_set_user_var::fix_fields
|
||||||
|
for the rationale).
|
||||||
|
*/
|
||||||
bool prohibit_cond_pushdown;
|
bool prohibit_cond_pushdown;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user