1
0
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:
Dave Gosselin
2025-04-24 15:03:05 -04:00
committed by Dave Gosselin
parent 07d71fdcf8
commit 62a1f0d990
8 changed files with 1467 additions and 26 deletions

View 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
#

View 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 #

View File

@@ -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.

View File

@@ -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

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;
} }
} }

View File

@@ -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;
/* /*