1
0
mirror of https://github.com/MariaDB/server.git synced 2025-12-04 17:23:46 +03:00

MDEV-12387 Push conditions into materialized subqueries

The logic and the implementation scheme are similar with the
MDEV-9197 Pushdown conditions into non-mergeable views/derived tables

How the push down is made on the example:

select * from t1
where a>3 and b>10 and
 (a,b) in (select x,max(y) from t2 group by x);

-->

select * from t1
where a>3 and b>10 and
  (a,b) in (select x,max(y)
            from t2
            where x>3
            group by x
            having max(y)>10);

The implementation scheme:

1. Search for the condition cond that depends only on the fields
   from the left part of the IN subquery (left_part)
2. Find fields F_group in the select of the right part of the
   IN subquery (right_part) that are used in the GROUP BY
3. Extract from the cond condition cond_where that depends only on the
   fields from the left_part that stay at the same places in the left_part
   (have the same indexes) as the F_group fields in the projection of the
   right_part
4. Transform cond_where so it can be pushed into the WHERE clause of the
   right_part and delete cond_where from the cond
5. Transform cond so it can be pushed into the HAVING clause of the right_part

The optimization is made in the
Item_in_subselect::pushdown_cond_for_in_subquery() and is controlled by the
variable condition_pushdown_for_subquery.

New test file in_subq_cond_pushdown.test is created.

There are also some changes made for setup_jtbm_semi_joins().
Now it is decomposed into the 2 procedures: setup_degenerate_jtbm_semi_joins()
that is called before optimize_cond() for cond and setup_jtbm_semi_joins()
that is called after optimize_cond().
New setup_jtbm_semi_joins() is made in the way so that the result of its work is
the same as if it was called before optimize_cond().

The code that is common for pushdown into materialized derived and into materialized
IN subqueries is factored out into pushdown_cond_for_derived(),
Item_in_subselect::pushdown_cond_for_in_subquery() and
st_select_lex::pushdown_cond_into_where_clause().
This commit is contained in:
Galina Shalygina
2018-05-15 23:45:59 +02:00
parent 569e3ad1ea
commit d3ff133390
30 changed files with 6115 additions and 504 deletions

View File

@@ -632,7 +632,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
2 DERIVED t1 system NULL NULL NULL NULL 1 100.00 2 DERIVED t1 system NULL NULL NULL NULL 1 100.00
Warnings: Warnings:
Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1 Note 1276 Field or reference 'sq.f2' of SELECT #3 was resolved in SELECT #1
Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `test`.`t2`.`f3` = 6 and `<subquery4>`.`f3` = 9 Note 1003 /* select#1 */ select 6 AS `f1` from <materialize> (/* select#4 */ select `test`.`t2`.`f3` from `test`.`t2` having `test`.`t2`.`f3` >= 8) semi join (`test`.`t2`) where `<subquery4>`.`f3` = 9 and `test`.`t2`.`f3` = 6
DROP TABLE t2,t1; DROP TABLE t2,t1;
# #
# MDEV-9462: Out of memory using explain on 2 empty tables # MDEV-9462: Out of memory using explain on 2 empty tables

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,759 @@
LET $no_pushdown=
SET STATEMENT optimizer_switch='condition_pushdown_for_subquery=off' FOR;
CREATE TABLE t1 (a INT, b INT, c INT, d INT);
CREATE TABLE t2 (e INT, f INT, g INT);
CREATE TABLE t3 (x INT, y INT);
INSERT INTO t1 VALUES
(1,1,18,1), (2,1,25,1), (1,3,40,1), (2,3,40,4),
(4,2,24,4), (3,2,23,1), (1,2,40,2), (3,4,17,2),
(5,5,65,1), (2,3,70,3), (1,4,35,3), (2,3,25,3),
(2,2,40,4), (1,4,55,1), (5,3,72,4), (1,2,70,5);
INSERT INTO t2 VALUES
(1,2,38), (2,3,15), (1,3,40), (1,4,35),
(2,2,70), (3,4,23), (5,5,12), (5,4,17),
(3,3,17), (4,2,24), (2,5,25), (5,1,65);
INSERT INTO t3 VALUES
(1,25), (1,18), (2,15), (4,24),
(1,35), (3,23), (3,17), (2,15);
CREATE VIEW v1 AS
(
SELECT t3.x AS v1_x, t3.y AS v1_y FROM t3 WHERE t3.x<=3
);
CREATE VIEW v2 AS
(
SELECT t2.e, t2.f, MAX(t2.g) AS max_g
FROM t2
GROUP BY t2.e
HAVING max_g>25
);
--echo # conjunctive subformula : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE t1.c<25 AND
(t1.a,t1.c) IN (SELECT t2.e,MAX(t2.g) FROM t2 WHERE t2.e<5 GROUP BY t2.e);
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted AND formula : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE t1.c>55 AND t1.b<4 AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted OR formula : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE (t1.c>60 OR t1.c<25) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted AND-OR formula : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE ((t1.c>60 OR t1.c<25) AND t1.b>2) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE ((t1.a<2 OR t1.d>3) AND t1.b>1) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # using view IN subquery defINition : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE t1.c>20 AND
(t1.a,t1.c) IN
(
SELECT v1_x,MAX(v1_y)
FROM v1
WHERE v1_x>1
GROUP BY v1_x
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # using equality : pushing into WHERE
LET $query=
SELECT * FROM t1,v1
WHERE t1.c>20 AND t1.c=v1_y AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE t1.a<2 AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted AND formula : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE t1.a>2 AND t1.a<5 AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted OR formula : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE (t1.a<2 OR t1.a>=4) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted AND-OR formula : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e,t2.f
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # extracted AND-OR formula : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE ((t1.a<2 OR t1.a=5) AND t1.b>3) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e,t2.f
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE ((t1.b<3 OR t1.d>2) AND t1.a<2) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # using equalities : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE t1.d=1 AND t1.a=t1.d AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # using equality : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE t1.d>1 AND t1.a=t1.d AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # using view IN subquery definition : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE t1.a<3 AND
(t1.a,t1.c) IN
(
SELECT v1_x,MAX(v1_y)
FROM v1
WHERE v1_x>1
GROUP BY v1_x
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # using equality : pushing into WHERE
LET $query=
SELECT * FROM t1,v1
WHERE t1.a=v1_x AND v1_x<2 AND v1_y>30 AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE
--echo # extracted OR formula : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE ((t1.b<3 OR t1.b=4) AND t1.a<3) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using addition : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE (t1.a+t1.c>41) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using substitution : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE (t1.c-t1.a<35) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using multiplication : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE (t1.c*t1.a>100) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using division : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE (t1.c/t1.a>30) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using BETWEEN : pushing into HAVING
LET $query=
SELECT * FROM t1
WHERE (t1.c BETWEEN 50 AND 100) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using addition : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE (t1.a+t1.b > 5) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e,t2.f
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using substitution : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE (t1.a-t1.b > 0) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e,t2.f
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using multiplication : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE (t1.a*t1.b > 6) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e,t2.f
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using division : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE (t1.b/t1.a > 2) AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e,t2.f
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula using BETWEEN : pushing into WHERE
LET $query=
SELECT * FROM t1
WHERE (t1.a BETWEEN 1 AND 3) AND
(t1.a,t1.c) IN
(
SELECT t2.e,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into HAVING of the IN subquery
--echo # conjunctive subformula : pushing into WHERE of the view from the IN subquery
LET $query=
SELECT * FROM t1
WHERE t1.c>3 AND
(t1.a,t1.b,t1.c) IN
(
SELECT v2.e,MAX(v2.f),v2.max_g
FROM v2
WHERE v2.e<5
GROUP BY v2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE of the IN subquery
--echo # conjunctive subformula : pushing into WHERE of the view
--echo # from the IN subquery
LET $query=
SELECT * FROM t1
WHERE t1.a>1 AND
(t1.a,t1.b,t1.c) IN
(
SELECT v2.e,MAX(v2.f),v2.max_g
FROM v2
WHERE v2.e<5
GROUP BY v2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE and HAVING
--echo # of the IN subquery
--echo # conjunctive subformula : pushing into WHERE of the view
--echo # from the IN subquery
LET $query=
SELECT * FROM t1
WHERE t1.a>1 AND t1.c<100 AND
(t1.a,t1.b,t1.c) IN
(
SELECT v2.e,MAX(v2.f),v2.max_g
FROM v2
WHERE v2.e<5
GROUP BY v2.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE of the IN subquery
--echo # extracted AND formula : pushing into HAVING of the derived table
--echo # from the IN subquery
LET $query=
SELECT * FROM t1
WHERE t1.a>1 AND
(t1.a,t1.b,t1.c) IN
(
SELECT d_tab.e,MAX(d_tab.f),d_tab.max_g
FROM
(
SELECT t2.e, t2.f, MAX(t2.g) AS max_g
FROM t2
GROUP BY t2.f
HAVING max_g>25
) as d_tab
WHERE d_tab.e<5
GROUP BY d_tab.e
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into HAVING of the derived table
--echo # conjunctive subformula : pushing into WHERE of the IN subquery from
--echo # the derived table
SELECT *
FROM t3,
(
SELECT t1.a,t1.b,max(t1.c) as max_c
FROM t1
WHERE t1.a>1 AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.e<5
GROUP BY t2.e
)
GROUP BY t1.a
) AS d_tab
WHERE d_tab.a=t3.x AND d_tab.b>2;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE of the derived table
--echo # extracted AND formula : pushing into WHERE of the IN subquery from
--echo # the derived table
SELECT *
FROM t3,
(
SELECT t1.a,t1.b,max(t1.c) as max_c
FROM t1
WHERE t1.a>1 AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
GROUP BY t2.e
HAVING t2.f<5
)
GROUP BY t1.a
) AS d_tab
WHERE d_tab.a=t3.x AND d_tab.a<5;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE and HAVING
--echo # of the derived table
--echo # extracted AND formula : pushing into WHERE of the IN subquery
--echo # from the derived table
LET $query=
SELECT *
FROM t3,
(
SELECT t1.a,t1.b,max(t1.c) as max_c
FROM t1
WHERE t1.a>1 AND
(t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
GROUP BY t2.e
HAVING t2.f<5
)
GROUP BY t1.a
) AS d_tab
WHERE d_tab.a=t3.x AND d_tab.a<5 AND d_tab.max_c<70;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE of the derived table
--echo # conjunctive subformula : pushing into HAVING of the IN subquery from
--echo # the derived table
SELECT *
FROM t3,
(
SELECT t1.a,t1.b,max(t1.c) as max_c
FROM t1
WHERE (t1.a,t1.b,t1.c) IN
(
SELECT t2.e,t2.f,MAX(t2.g)
FROM t2
WHERE t2.f<4
GROUP BY t2.f
)
GROUP BY t1.a
HAVING t1.b<5
) AS d_tab
WHERE d_tab.a=t3.x AND d_tab.a<5;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE
--echo # using WINDOW FUNCTIONS : using MAX function
LET $query=
SELECT * FROM t1
WHERE (t1.b>1) AND
(t1.b, t1.c) IN
(
SELECT t2.f, MAX(t2.g) OVER (PARTITION BY t2.f)
FROM t2
WHERE t2.e<5
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
--echo # conjunctive subformula : pushing into WHERE
--echo # using WINDOW FUNCTIONS : using SUM function
LET $query=
SELECT * FROM t1
WHERE (t1.b>1) AND
(t1.b, t1.c) IN
(
SELECT t2.f, CAST(SUM(t2.g) OVER (PARTITION BY t2.f) AS INT)
FROM t2
WHERE t2.e<5
)
;
EVAL $no_pushdown $query;
EVAL $query;
EVAL EXPLAIN $query;
EVAL EXPLAIN FORMAT=JSON $query;
DROP TABLE t1,t2,t3;
DROP VIEW v1,v2;

View File

@@ -665,7 +665,8 @@ The following options may be given as the first argument:
join_cache_hashed, join_cache_bka, join_cache_hashed, join_cache_bka,
optimize_join_buffer_size, table_elimination, optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities, extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized condition_pushdown_for_derived, split_materialized,
condition_pushdown_for_subquery
--optimizer-use-condition-selectivity=# --optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial takes into account to calculate cardinality of a partial
@@ -1514,7 +1515,7 @@ old-style-user-limits FALSE
optimizer-prune-level 1 optimizer-prune-level 1
optimizer-search-depth 62 optimizer-search-depth 62
optimizer-selectivity-sampling-limit 100 optimizer-selectivity-sampling-limit 100
optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
optimizer-use-condition-selectivity 1 optimizer-use-condition-selectivity 1
performance-schema FALSE performance-schema FALSE
performance-schema-accounts-size -1 performance-schema-accounts-size -1

View File

@@ -1925,7 +1925,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
Warnings: Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7) Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
SELECT * FROM t1 SELECT * FROM t1
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
a b a b

View File

@@ -1963,7 +1963,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
Warnings: Warnings:
Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2`) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7) Note 1003 /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from <materialize> (/* select#2 */ select max(`test`.`t2`.`c`) from `test`.`t2` having `MAX(c)` is null or `MAX(c)` = 7) join `test`.`t1` where `test`.`t1`.`b` = 7 and `test`.`t1`.`a` = `<subquery2>`.`MAX(c)` and (<cache>(`<subquery2>`.`MAX(c)` is null) or `<subquery2>`.`MAX(c)` = 7)
SELECT * FROM t1 SELECT * FROM t1
WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b); WHERE a IN (SELECT MAX(c) FROM t2) AND b=7 AND (a IS NULL OR a=b);
a b a b

View File

@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch; SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value; SELECT @start_global_value;
@start_global_value @start_global_value
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
select @@global.optimizer_switch; select @@global.optimizer_switch;
@@global.optimizer_switch @@global.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
select @@session.optimizer_switch; select @@session.optimizer_switch;
@@session.optimizer_switch @@session.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
show global variables like 'optimizer_switch'; show global variables like 'optimizer_switch';
Variable_name Value Variable_name Value
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
show session variables like 'optimizer_switch'; show session variables like 'optimizer_switch';
Variable_name Value Variable_name Value
optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
select * from information_schema.global_variables where variable_name='optimizer_switch'; select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
select * from information_schema.session_variables where variable_name='optimizer_switch'; select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
set global optimizer_switch=10; set global optimizer_switch=10;
set session optimizer_switch=5; set session optimizer_switch=5;
select @@global.optimizer_switch; select @@global.optimizer_switch;
@@global.optimizer_switch @@global.optimizer_switch
index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
select @@session.optimizer_switch; select @@session.optimizer_switch;
@@session.optimizer_switch @@session.optimizer_switch
index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
set global optimizer_switch="index_merge_sort_union=on"; set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off"; set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch; select @@global.optimizer_switch;
@@global.optimizer_switch @@global.optimizer_switch
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
select @@session.optimizer_switch; select @@session.optimizer_switch;
@@session.optimizer_switch @@session.optimizer_switch
index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
show global variables like 'optimizer_switch'; show global variables like 'optimizer_switch';
Variable_name Value Variable_name Value
optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
show session variables like 'optimizer_switch'; show session variables like 'optimizer_switch';
Variable_name Value Variable_name Value
optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
select * from information_schema.global_variables where variable_name='optimizer_switch'; select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
select * from information_schema.session_variables where variable_name='optimizer_switch'; select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
set session optimizer_switch="default"; set session optimizer_switch="default";
select @@session.optimizer_switch; select @@session.optimizer_switch;
@@session.optimizer_switch @@session.optimizer_switch
index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on'); set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings: Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
set global optimizer_switch=1.1; set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch' ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1; set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value; SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch; SELECT @@global.optimizer_switch;
@@global.optimizer_switch @@global.optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on

View File

@@ -2673,17 +2673,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH VARIABLE_NAME OPTIMIZER_SWITCH
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
VARIABLE_SCOPE SESSION VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY

View File

@@ -2883,17 +2883,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH VARIABLE_NAME OPTIMIZER_SWITCH
SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
VARIABLE_SCOPE SESSION VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,default ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY

View File

@@ -7635,6 +7635,231 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
} }
/**
@brief
Prepare AND/OR formula for extraction of a pushable condition
@param checker the checker callback function to be applied to the nodes
of the tree of the object
@param arg parameter to be passed to the checker
@details
This method recursively traverses this AND/OR condition and for each
subformula of the condition it checks whether it can be usable for the
extraction of a pushable condition. The criteria of pushability of
a subformula is checked by the callback function 'checker' with one
parameter arg. The subformulas that are not usable are marked with
the flag NO_EXTRACTION_FL.
@note
This method is called before any call of build_pushable_cond.
The flag NO_EXTRACTION_FL set in a subformula allows to avoid building
clones for the subformulas that are not used in the pushable condition.
@note
This method is called for pushdown conditions into materialized
derived tables/views optimization.
Item::pushable_cond_checker_for_derived() is passed as the actual callback
function.
Also it is called for pushdown conditions in materialized IN subqueries.
Item::pushable_cond_checker_for_subquery is passed as the actual
callback function.
*/
void Item::check_pushable_cond(Pushdown_checker checker, uchar *arg)
{
clear_extraction_flag();
if (type() == Item::COND_ITEM)
{
bool and_cond= ((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC;
List_iterator<Item> li(*((Item_cond*) this)->argument_list());
uint count= 0;
Item *item;
while ((item=li++))
{
item->check_pushable_cond(checker, arg);
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
count++;
else if (!and_cond)
break;
}
if ((and_cond && count == 0) || item)
{
set_extraction_flag(NO_EXTRACTION_FL);
if (and_cond)
li.rewind();
while ((item= li++))
item->clear_extraction_flag();
}
}
else if (!((this->*checker) (arg)))
set_extraction_flag(NO_EXTRACTION_FL);
}
/**
@brief
Build condition extractable from this condition for pushdown
@param thd the thread handle
@param checker the checker callback function to be applied to the
equal items of multiple equality items
@param arg parameter to be passed to the checker
@details
This method finds out what condition that can be pushed down can be
extracted from this condition. If such condition C exists the
method builds the item for it. The method uses the flag NO_EXTRACTION_FL
set by the preliminary call of the method check_pushable_cond() to figure
out whether a subformula is pushable or not.
In the case when this item is a multiple equality a checker method is
called to find the equal fields to build a new equality that can be
pushed down.
@note
The built condition C is always implied by the condition cond
(cond => C). The method tries to build the most restrictive such
condition (i.e. for any other condition C' such that cond => C'
we have C => C').
@note
The build item is not ready for usage: substitution for the field items
has to be done and it has to be re-fixed.
@note
This method is called for pushdown conditions into materialized
derived tables/views optimization.
Item::pushable_equality_checker_for_derived() is passed as the actual
callback function.
Also it is called for pushdown conditions into materialized IN subqueries.
Item::pushable_equality_checker_for_subquery() is passed as the actual
callback function.
@retval
the built condition pushable into if such a condition exists
NULL if there is no such a condition
*/
Item *Item::build_pushable_cond(THD *thd,
Pushdown_checker checker,
uchar *arg)
{
bool is_multiple_equality= type() == Item::FUNC_ITEM &&
((Item_func*) this)->functype() == Item_func::MULT_EQUAL_FUNC;
if (get_extraction_flag() == NO_EXTRACTION_FL)
return 0;
if (type() == Item::COND_ITEM)
{
bool cond_and= false;
Item_cond *new_cond;
if (((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC)
{
cond_and= true;
new_cond= new (thd->mem_root) Item_cond_and(thd);
}
else
new_cond= new (thd->mem_root) Item_cond_or(thd);
if (!new_cond)
return 0;
List_iterator<Item> li(*((Item_cond*) this)->argument_list());
Item *item;
bool is_fix_needed= false;
while ((item=li++))
{
if (item->get_extraction_flag() == NO_EXTRACTION_FL)
{
if (!cond_and)
return 0;
continue;
}
Item *fix= item->build_pushable_cond(thd, checker, arg);
if (!fix && !cond_and)
return 0;
if (!fix)
continue;
if (fix->type() == Item::COND_ITEM &&
((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
is_fix_needed= true;
if (new_cond->argument_list()->push_back(fix, thd->mem_root))
return 0;
}
if (is_fix_needed)
new_cond->fix_fields(thd, 0);
switch (new_cond->argument_list()->elements)
{
case 0:
return 0;
case 1:
return new_cond->argument_list()->head();
default:
return new_cond;
}
}
else if (is_multiple_equality)
{
Item *new_cond= NULL;
int i= 0;
Item_equal *item_equal= (Item_equal *) this;
Item *left_item = item_equal->get_const();
Item_equal_fields_iterator it(*item_equal);
Item *item;
Item *right_item;
if (!left_item)
{
while ((item=it++))
{
left_item= ((item->*checker) (arg)) ? item : NULL;
if (left_item)
break;
}
}
if (!left_item)
return 0;
while ((item=it++))
{
right_item= ((item->*checker) (arg)) ? item : NULL;
if (!right_item)
continue;
Item_func_eq *eq= 0;
Item *left_item_clone= left_item->build_clone(thd);
Item *right_item_clone= item->build_clone(thd);
if (left_item_clone && right_item_clone)
{
left_item_clone->set_item_equal(NULL);
right_item_clone->set_item_equal(NULL);
eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
left_item_clone);
}
if (eq)
{
i++;
switch (i)
{
case 1:
new_cond= eq;
break;
case 2:
new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
break;
default:
if (((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
thd->mem_root))
return 0;
break;
}
}
}
if (new_cond && new_cond->fix_fields(thd, &new_cond))
return 0;
return new_cond;
}
else if (get_extraction_flag() != NO_EXTRACTION_FL)
return build_clone(thd);
return 0;
}
static static
Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel) Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
{ {
@@ -7754,18 +7979,18 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
} }
static static
Grouping_tmp_field *find_matching_grouping_field(Item *item, Field_pair *find_matching_grouping_field(Item *item,
st_select_lex *sel) st_select_lex *sel)
{ {
DBUG_ASSERT(item->type() == Item::FIELD_ITEM || DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
(item->type() == Item::REF_ITEM && (item->type() == Item::REF_ITEM &&
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF)); ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
List_iterator<Grouping_tmp_field> li(sel->grouping_tmp_fields); List_iterator<Field_pair> li(sel->grouping_tmp_fields);
Grouping_tmp_field *gr_field; Field_pair *gr_field;
Item_field *field_item= (Item_field *) (item->real_item()); Item_field *field_item= (Item_field *) (item->real_item());
while ((gr_field= li++)) while ((gr_field= li++))
{ {
if (field_item->field == gr_field->tmp_field) if (field_item->field == gr_field->field)
return gr_field; return gr_field;
} }
Item_equal *item_equal= item->get_item_equal(); Item_equal *item_equal= item->get_item_equal();
@@ -7779,7 +8004,7 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item,
li.rewind(); li.rewind();
while ((gr_field= li++)) while ((gr_field= li++))
{ {
if (field_item->field == gr_field->tmp_field) if (field_item->field == gr_field->field)
return gr_field; return gr_field;
} }
} }
@@ -7788,26 +8013,25 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item,
} }
Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd, Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
uchar *arg)
{ {
st_select_lex *sel= (st_select_lex *)arg; st_select_lex *sel= (st_select_lex *)arg;
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel); Field_pair *gr_field= find_matching_grouping_field(this, sel);
if (gr_field) if (gr_field)
return gr_field->producing_item->build_clone(thd); return gr_field->corresponding_item->build_clone(thd);
return this; return this;
} }
Item * Item *
Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd, Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
uchar *arg) uchar *arg)
{ {
if (!item_equal) if (!item_equal)
return this; return this;
st_select_lex *sel= (st_select_lex *)arg; st_select_lex *sel= (st_select_lex *)arg;
Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel); Field_pair *gr_field= find_matching_grouping_field(this, sel);
return gr_field->producing_item->build_clone(thd); return gr_field->corresponding_item->build_clone(thd);
} }
void Item_field::print(String *str, enum_query_type query_type) void Item_field::print(String *str, enum_query_type query_type)

View File

@@ -569,6 +569,7 @@ typedef bool (Item::*Item_processor) (void *arg);
typedef bool (Item::*Item_analyzer) (uchar **argp); typedef bool (Item::*Item_analyzer) (uchar **argp);
typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg); typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg); typedef void (*Cond_traverser) (const Item *item, void *arg);
typedef bool (Item::*Pushdown_checker) (uchar *arg);
struct st_cond_statistic; struct st_cond_statistic;
@@ -601,6 +602,7 @@ public:
String_copier_for_item(THD *thd): m_thd(thd) { } String_copier_for_item(THD *thd): m_thd(thd) { }
}; };
class Item: public Value_source, class Item: public Value_source,
public Type_all_attributes public Type_all_attributes
{ {
@@ -1647,7 +1649,15 @@ public:
or can be converted to such an exression using equalities. or can be converted to such an exression using equalities.
Not to be used for AND/OR formulas. Not to be used for AND/OR formulas.
*/ */
virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; } virtual bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return false; }
/*
TRUE if the expression depends only on fields from the left part of
IN subquery or can be converted to such an expression using equalities.
Not to be used for AND/OR formulas.
*/
virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return false; }
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; } virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
virtual bool find_function_processor (void *arg) { return 0; } virtual bool find_function_processor (void *arg) { return 0; }
@@ -1825,8 +1835,12 @@ public:
{ return this; } { return this; }
virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg) virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ return this; } { return this; }
virtual Item *derived_grouping_field_transformer_for_where(THD *thd, virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
uchar *arg) { return this; }
/* Now is not used. */
virtual Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{ return this; }
virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ return this; } { return this; }
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg) virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
{ return this; } { return this; }
@@ -2023,6 +2037,33 @@ public:
{ {
marker &= ~EXTRACTION_MASK; marker &= ~EXTRACTION_MASK;
} }
void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg);
bool pushable_cond_checker_for_derived(uchar *arg)
{
return excl_dep_on_table(*((table_map *)arg));
}
bool pushable_cond_checker_for_subquery(uchar *arg)
{
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
}
Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
Item *build_pushable_cond(THD *thd,
Pushdown_checker checker,
uchar *arg);
/*
Checks if this item depends only on the arg table
*/
bool pushable_equality_checker_for_derived(uchar *arg)
{
return (used_tables() == *((table_map *)arg));
}
/*
Checks if this item consists in the left part of arg IN subquery predicate
*/
bool pushable_equality_checker_for_subquery(uchar *arg)
{
return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
}
}; };
MEM_ROOT *get_thd_memroot(THD *thd); MEM_ROOT *get_thd_memroot(THD *thd);
@@ -2151,6 +2192,17 @@ protected:
} }
return true; return true;
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
for (uint i= 0; i < arg_count; i++)
{
if (args[i]->const_item())
continue;
if (!args[i]->excl_dep_on_in_subq_left_part(subq_pred))
return false;
}
return true;
}
public: public:
Item_args(void) Item_args(void)
:args(NULL), arg_count(0) :args(NULL), arg_count(0)
@@ -3046,10 +3098,13 @@ public:
virtual Item *update_value_transformer(THD *thd, uchar *select_arg); virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg); Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
bool excl_dep_on_table(table_map tab_map); bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel); bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
bool cleanup_excluding_fields_processor(void *arg) bool cleanup_excluding_fields_processor(void *arg)
{ return field ? 0 : cleanup_processor(arg); } { return field ? 0 : cleanup_processor(arg); }
bool cleanup_excluding_const_fields_processor(void *arg) bool cleanup_excluding_const_fields_processor(void *arg)
@@ -4874,6 +4929,8 @@ public:
} }
bool excl_dep_on_grouping_fields(st_select_lex *sel) bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return (*ref)->excl_dep_on_grouping_fields(sel); } { return (*ref)->excl_dep_on_grouping_fields(sel); }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{ return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }
bool cleanup_excluding_fields_processor(void *arg) bool cleanup_excluding_fields_processor(void *arg)
{ {
Item *item= real_item(); Item *item= real_item();
@@ -5188,10 +5245,12 @@ public:
} }
bool excl_dep_on_table(table_map tab_map); bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel); bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg); Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg); Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Item *derived_grouping_field_transformer_for_where(THD *thd, Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
uchar *arg); Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
void save_val(Field *to) void save_val(Field *to)
{ {
@@ -6110,7 +6169,11 @@ public:
{ return convert_to_basic_const_item(thd); } { return convert_to_basic_const_item(thd); }
Item *derived_field_transformer_for_where(THD *thd, uchar *arg) Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); } { return convert_to_basic_const_item(thd); }
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); }
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); }
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); } { return convert_to_basic_const_item(thd); }
}; };

View File

@@ -1272,7 +1272,11 @@ public:
{ reset_first_arg_if_needed(); return this; } { reset_first_arg_if_needed(); return this; }
Item *derived_field_transformer_for_where(THD *thd, uchar *arg) Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; } { reset_first_arg_if_needed(); return this; }
Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg) Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; }
Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; }
Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; } { reset_first_arg_if_needed(); return this; }
}; };
@@ -3135,6 +3139,8 @@ public:
{ {
return used_tables() & tab_map; return used_tables() & tab_map;
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
friend class Item_equal_fields_iterator; friend class Item_equal_fields_iterator;
bool count_sargable_conds(void *arg); bool count_sargable_conds(void *arg);
friend class Item_equal_iterator<List_iterator_fast,Item>; friend class Item_equal_iterator<List_iterator_fast,Item>;

View File

@@ -326,6 +326,11 @@ public:
return Item_args::excl_dep_on_grouping_fields(sel); return Item_args::excl_dep_on_grouping_fields(sel);
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
}
/* /*
We assume the result of any function that has a TIMESTAMP argument to be We assume the result of any function that has a TIMESTAMP argument to be
timezone-dependent, since a TIMESTAMP value in both numeric and string timezone-dependent, since a TIMESTAMP value in both numeric and string

View File

@@ -134,6 +134,11 @@ public:
return Item_args::excl_dep_on_grouping_fields(sel); return Item_args::excl_dep_on_grouping_fields(sel);
} }
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
}
bool check_vcol_func_processor(void *arg) {return FALSE; } bool check_vcol_func_processor(void *arg) {return FALSE; }
Item *get_copy(THD *thd) Item *get_copy(THD *thd)
{ return get_item_copy<Item_row>(thd, this); } { return get_item_copy<Item_row>(thd, this); }

View File

@@ -33,6 +33,7 @@ class subselect_hash_sj_engine;
class Item_bool_func2; class Item_bool_func2;
class Comp_creator; class Comp_creator;
class With_element; class With_element;
class Field_pair;
typedef class st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
@@ -570,6 +571,8 @@ public:
*/ */
bool is_registered_semijoin; bool is_registered_semijoin;
List<Field_pair> corresponding_fields;
/* /*
Used to determine how this subselect item is represented in the item tree, Used to determine how this subselect item is represented in the item tree,
in case there is a need to locate it there and replace with something else. in case there is a need to locate it there and replace with something else.
@@ -741,6 +744,8 @@ public:
return 0; return 0;
}; };
bool pushdown_cond_for_in_subquery(THD *thd, Item *cond);
friend class Item_ref_null_helper; friend class Item_ref_null_helper;
friend class Item_is_not_null_test; friend class Item_is_not_null_test;
friend class Item_in_optimizer; friend class Item_in_optimizer;
@@ -852,7 +857,6 @@ protected:
void set_row(List<Item> &item_list, Item_cache **row); void set_row(List<Item> &item_list, Item_cache **row);
}; };
class subselect_single_select_engine: public subselect_engine class subselect_single_select_engine: public subselect_engine
{ {
bool prepared; /* simple subselect is prepared */ bool prepared; /* simple subselect is prepared */
@@ -886,9 +890,10 @@ public:
friend class subselect_hash_sj_engine; friend class subselect_hash_sj_engine;
friend class Item_in_subselect; friend class Item_in_subselect;
friend bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, friend bool execute_degenerate_jtbm_semi_join(THD *thd,
Item **join_where); TABLE_LIST *tbl,
Item_in_subselect *subq_pred,
List<Item> &eq_list);
}; };

View File

@@ -5436,12 +5436,435 @@ int select_value_catcher::send_data(List<Item> &items)
} }
/**
@brief
Conjugate conditions after optimize_cond() call
@param thd the thread handle
@param cond the condition where to attach new conditions
@param cond_eq IN/OUT the multiple equalities of cond
@param new_conds IN/OUT the list of conditions needed to add
@param cond_value the returned value of the condition
@details
The method creates new condition through conjunction of cond and
the conditions from new_conds list.
The method is called after optimize_cond() for cond. The result
of the conjunction should be the same as if it was done before the
the optimize_cond() call.
@retval NULL if an error occurs
@retval otherwise the created condition
*/
Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
COND_EQUAL **cond_eq,
List<Item> &new_conds,
Item::cond_result *cond_value)
{
COND_EQUAL new_cond_equal;
Item *item;
Item_equal *equality;
bool is_simplified_cond= false;
List_iterator<Item> li(new_conds);
List_iterator_fast<Item_equal> it(new_cond_equal.current_level);
/* /*
Setup JTBM join tabs for execution Creates multiple equalities new_cond_equal from new_conds list
equalities. If multiple equality can't be created or the condition
from new_conds list isn't an equality the method leaves it in new_conds
list.
The equality can't be converted into the multiple equality if it
is a knowingly false or true equality.
For example, (3 = 1) equality.
*/
while ((item=li++))
{
if (item->type() == Item::FUNC_ITEM &&
((Item_func *) item)->functype() == Item_func::EQ_FUNC &&
check_simple_equality(thd,
Item::Context(Item::ANY_SUBST,
((Item_func_equal *)item)->compare_type_handler(),
((Item_func_equal *)item)->compare_collation()),
((Item_func *)item)->arguments()[0]->real_item(),
((Item_func *)item)->arguments()[1]->real_item(),
&new_cond_equal))
li.remove();
}
it.rewind();
if (cond && cond->type() == Item::COND_ITEM &&
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
/*
cond is an AND-condition.
The method conjugates the AND-condition cond, created multiple
equalities new_cond_equal and remain conditions from new_conds.
First, the method disjoins multiple equalities of cond and
merges new_cond_equal multiple equalities with these equalities.
It checks if after the merge the multiple equalities are knowingly
true or false equalities.
It attaches to cond the conditions from new_conds list and the result
of the merge of multiple equalities. The multiple equalities are
attached only to the upper level of AND-condition cond. So they
should be pushed down to the inner levels of cond AND-condition
if needed. It is done by propagate_new_equalities().
*/
COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->m_cond_equal;
List<Item_equal> *cond_equalities= &cond_equal->current_level;
List<Item> *and_args= ((Item_cond_and *)cond)->argument_list();
and_args->disjoin((List<Item> *) cond_equalities);
and_args->append(&new_conds);
while ((equality= it++))
{
equality->upper_levels= 0;
equality->merge_into_list(thd, cond_equalities, false, false);
}
List_iterator_fast<Item_equal> ei(*cond_equalities);
while ((equality= ei++))
{
if (equality->const_item() && !equality->val_int())
is_simplified_cond= true;
equality->fixed= 0;
if (equality->fix_fields(thd, NULL))
return NULL;
}
and_args->append((List<Item> *) cond_equalities);
*cond_eq= &((Item_cond_and *) cond)->m_cond_equal;
propagate_new_equalities(thd, cond, cond_equalities,
cond_equal->upper_levels,
&is_simplified_cond);
cond= cond->propagate_equal_fields(thd,
Item::Context_boolean(),
cond_equal);
}
else
{
/*
cond isn't AND-condition or is NULL.
There can be several cases:
1. cond is a multiple equality.
In this case cond is merged with the multiple equalities of
new_cond_equal.
The new condition is created with the conjunction of new_conds
list conditions and the result of merge of multiple equalities.
2. cond is NULL
The new condition is created from the conditions of new_conds
list and multiple equalities from new_cond_equal.
3. Otherwise
In this case the new condition is created from cond, remain conditions
from new_conds list and created multiple equalities from
new_cond_equal.
*/
List<Item> new_conds_list;
/* Flag is set to true if cond is a multiple equality */
bool is_mult_eq= (cond && cond->type() == Item::FUNC_ITEM &&
((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC);
if (cond && !is_mult_eq &&
new_conds_list.push_back(cond, thd->mem_root))
return NULL;
if (new_conds.elements > 0)
{
li.rewind();
while ((item=li++))
{
if (!item->fixed && item->fix_fields(thd, NULL))
return NULL;
if (item->const_item() && !item->val_int())
is_simplified_cond= true;
}
if (new_conds.elements > 1)
new_conds_list.append(&new_conds);
else
{
li.rewind();
item= li++;
if (new_conds_list.push_back(item, thd->mem_root))
return NULL;
}
}
if (new_cond_equal.current_level.elements > 0)
{
if (is_mult_eq)
{
Item_equal *eq_cond= (Item_equal *)cond;
eq_cond->upper_levels= 0;
eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
false, false);
while ((equality= it++))
{
if (equality->const_item() && !equality->val_int())
is_simplified_cond= true;
}
if (new_cond_equal.current_level.elements +
new_conds_list.elements == 1)
{
it.rewind();
equality= it++;
equality->fixed= 0;
if (equality->fix_fields(thd, NULL))
return NULL;
}
*cond_eq= &new_cond_equal;
}
new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
}
if (new_conds_list.elements > 1)
{
Item_cond_and *and_cond=
new (thd->mem_root) Item_cond_and(thd, new_conds_list);
and_cond->m_cond_equal.copy(new_cond_equal);
cond= (Item *)and_cond;
*cond_eq= &((Item_cond_and *)cond)->m_cond_equal;
}
else
{
List_iterator_fast<Item> iter(new_conds_list);
cond= iter++;
}
if (!cond->fixed && cond->fix_fields(thd, NULL))
return NULL;
if (new_cond_equal.current_level.elements > 0)
cond= cond->propagate_equal_fields(thd,
Item::Context_boolean(),
&new_cond_equal);
}
/*
If it was found that some of the created condition parts are knowingly
true or false equalities the method calls removes_eq_cond() to remove them
from cond and set the cond_value to the appropriate value.
*/
if (is_simplified_cond)
cond= cond->remove_eq_conds(thd, cond_value, true);
return cond;
}
/**
@brief Materialize a degenerate jtbm semi join
@param thd thread handler
@param tbl table list for the target jtbm semi join table
@param subq_pred IN subquery predicate with the degenerate jtbm semi join
@param eq_list IN/OUT the list where to add produced equalities
@details
The method materializes the degenerate jtbm semi join for the
subquery from the IN subquery predicate subq_pred taking table
as the target for materialization.
Any degenerate table is guaranteed to produce 0 or 1 record.
Examples of both cases:
select * from ot where col in (select ... from it where 2>3)
select * from ot where col in (select MY_MIN(it.key) from it)
in this case, there is no necessity to create a temp.table for
materialization.
We now just need to
1. Check whether 1 or 0 records are produced, setup this as a
constant join tab.
2. Create a dummy temporary table, because all of the join
optimization code relies on TABLE object being present.
In the case when materialization produces one row the function
additionally creates equalities between the expressions from the
left part of the IN subquery predicate and the corresponding
columns of the produced row. These equalities are added to the
list eq_list. They are supposed to be conjuncted with the condition
of the WHERE clause.
@retval TRUE if an error occurs
@retval FALSE otherwise
*/
bool execute_degenerate_jtbm_semi_join(THD *thd,
TABLE_LIST *tbl,
Item_in_subselect *subq_pred,
List<Item> &eq_list)
{
DBUG_ENTER("execute_degenerate_jtbm_semi_join");
select_value_catcher *new_sink;
DBUG_ASSERT(subq_pred->engine->engine_type() ==
subselect_engine::SINGLE_SELECT_ENGINE);
subselect_single_select_engine *engine=
(subselect_single_select_engine*)subq_pred->engine;
if (!(new_sink= new (thd->mem_root) select_value_catcher(thd, subq_pred)))
DBUG_RETURN(TRUE);
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
engine->select_lex->join->change_result(new_sink, NULL) ||
engine->exec())
{
DBUG_RETURN(TRUE);
}
subq_pred->is_jtbm_const_tab= TRUE;
if (new_sink->assigned)
{
/*
Subselect produced one row, which is saved in new_sink->row.
Save "left_expr[i] == row[i]" equalities into the eq_list.
*/
subq_pred->jtbm_const_row_found= TRUE;
Item *eq_cond;
for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
{
eq_cond=
new (thd->mem_root) Item_func_eq(thd,
subq_pred->left_expr->element_index(i),
new_sink->row[i]);
if (!eq_cond || eq_list.push_back(eq_cond, thd->mem_root))
DBUG_RETURN(TRUE);
}
}
else
{
/* Subselect produced no rows. Just set the flag */
subq_pred->jtbm_const_row_found= FALSE;
}
TABLE *dummy_table;
if (!(dummy_table= create_dummy_tmp_table(thd)))
DBUG_RETURN(TRUE);
tbl->table= dummy_table;
tbl->table->pos_in_table_list= tbl;
/*
Note: the table created above may be freed by:
1. JOIN_TAB::cleanup(), when the parent join is a regular join.
2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
degenerate join (e.g. one with "Impossible where").
*/
setup_table_map(tbl->table, tbl, tbl->jtbm_table_no);
DBUG_RETURN(FALSE);
}
/**
@brief
Execute degenerate jtbm semi joins before optimize_cond() for parent
@param join the parent join for jtbm semi joins
@param join_list the list of tables where jtbm semi joins are processed
@param eq_list IN/OUT the list where to add equalities produced after
materialization of single-row degenerate jtbm semi joins
@details
The method traverses join_list trying to find any degenerate jtbm semi
joins for subqueries of IN predicates. For each degenerate jtbm
semi join execute_degenerate_jtbm_semi_join() is called. As a result
of this call new equalities that substitute for single-row materialized
jtbm semi join are added to eq_list.
In the case when a table is nested in another table 'nested_join' the
method is recursively called for the join_list of the 'nested_join' trying
to find in the list any degenerate jtbm semi joins. Currently a jtbm semi
join may occur in a mergeable semi join nest.
@retval TRUE if an error occurs
@retval FALSE otherwise
*/
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
List<TABLE_LIST> *join_list,
List<Item> &eq_list)
{
TABLE_LIST *table;
NESTED_JOIN *nested_join;
List_iterator<TABLE_LIST> li(*join_list);
THD *thd= join->thd;
DBUG_ENTER("setup_degenerate_jtbm_semi_joins");
while ((table= li++))
{
Item_in_subselect *subq_pred;
if ((subq_pred= table->jtbm_subselect))
{
JOIN *subq_join= subq_pred->unit->first_select()->join;
if (!subq_join->tables_list || !subq_join->table_count)
{
if (execute_degenerate_jtbm_semi_join(thd,
table,
subq_pred,
eq_list))
DBUG_RETURN(TRUE);
join->is_orig_degenerated= true;
}
}
if ((nested_join= table->nested_join))
{
if (setup_degenerate_jtbm_semi_joins(join,
&nested_join->join_list,
eq_list))
DBUG_RETURN(TRUE);
}
}
DBUG_RETURN(FALSE);
}
/**
@brief
Optimize jtbm semi joins for materialization
@param join the parent join for jtbm semi joins
@param join_list the list of TABLE_LIST objects where jtbm semi join
can occur
@param eq_list IN/OUT the list where to add produced equalities
@details
This method is called by the optimizer after the call of
optimize_cond() for parent select.
The method traverses join_list trying to find any jtbm semi joins for
subqueries from IN predicates and optimizes them.
After the optimization some of jtbm semi joins may become degenerate.
For example the subquery 'SELECT MAX(b) FROM t2' from the query
SELECT * FROM t1 WHERE 4 IN (SELECT MAX(b) FROM t2);
will become degenerate if there is an index on t2.b.
If a subquery becomes degenerate it is handled by the function
execute_degenerate_jtbm_semi_join().
Otherwise the method creates a temporary table in which the subquery
of the jtbm semi join will be materialied.
The function saves the equalities between all pairs of the expressions
from the left part of the IN subquery predicate and the corresponding
columns of the subquery from the predicate in eq_list appending them
to the list. The equalities of eq_list will be later conjucted with the
condition of the WHERE clause.
In the case when a table is nested in another table 'nested_join' the
method is recursively called for the join_list of the 'nested_join' trying
to find in the list any degenerate jtbm semi joins. Currently a jtbm semi
join may occur in a mergeable semi join nest.
@retval TRUE if an error occurs
@retval FALSE otherwise
*/ */
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
Item **join_where) List<Item> &eq_list)
{ {
TABLE_LIST *table; TABLE_LIST *table;
NESTED_JOIN *nested_join; NESTED_JOIN *nested_join;
@@ -5451,16 +5874,15 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
while ((table= li++)) while ((table= li++))
{ {
Item_in_subselect *item; Item_in_subselect *subq_pred;
if ((item= table->jtbm_subselect)) if ((subq_pred= table->jtbm_subselect))
{ {
Item_in_subselect *subq_pred= item;
double rows; double rows;
double read_time; double read_time;
/* /*
Perform optimization of the subquery, so that we know estmated Perform optimization of the subquery, so that we know estimated
- cost of materialization process - cost of materialization process
- how many records will be in the materialized temp.table - how many records will be in the materialized temp.table
*/ */
@@ -5473,103 +5895,36 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
if (!subq_join->tables_list || !subq_join->table_count) if (!subq_join->tables_list || !subq_join->table_count)
{ {
/* if (!join->is_orig_degenerated &&
A special case; subquery's join is degenerate, and it either produces execute_degenerate_jtbm_semi_join(thd, table, subq_pred,
0 or 1 record. Examples of both cases: eq_list))
select * from ot where col in (select ... from it where 2>3)
select * from ot where col in (select MY_MIN(it.key) from it)
in this case, the subquery predicate has not been setup for
materialization. In particular, there is no materialized temp.table.
We'll now need to
1. Check whether 1 or 0 records are produced, setup this as a
constant join tab.
2. Create a dummy temporary table, because all of the join
optimization code relies on TABLE object being present (here we
follow a bad tradition started by derived tables)
*/
DBUG_ASSERT(subq_pred->engine->engine_type() ==
subselect_engine::SINGLE_SELECT_ENGINE);
subselect_single_select_engine *engine=
(subselect_single_select_engine*)subq_pred->engine;
select_value_catcher *new_sink;
if (!(new_sink=
new (thd->mem_root) select_value_catcher(thd, subq_pred)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (new_sink->setup(&engine->select_lex->join->fields_list) ||
engine->select_lex->join->change_result(new_sink, NULL) ||
engine->exec())
{
DBUG_RETURN(TRUE);
}
subq_pred->is_jtbm_const_tab= TRUE;
if (new_sink->assigned)
{
subq_pred->jtbm_const_row_found= TRUE;
/*
Subselect produced one row, which is saved in new_sink->row.
Inject "left_expr[i] == row[i] equalities into parent's WHERE.
*/
Item *eq_cond;
for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
{
eq_cond= new (thd->mem_root)
Item_func_eq(thd, subq_pred->left_expr->element_index(i),
new_sink->row[i]);
if (!eq_cond)
DBUG_RETURN(1);
if (!((*join_where)= and_items(thd, *join_where, eq_cond)) ||
(*join_where)->fix_fields(thd, join_where))
DBUG_RETURN(1);
}
}
else
{
/* Subselect produced no rows. Just set the flag, */
subq_pred->jtbm_const_row_found= FALSE;
}
/* Set up a dummy TABLE*, optimizer code needs JOIN_TABs to have TABLE */
TABLE *dummy_table;
if (!(dummy_table= create_dummy_tmp_table(thd)))
DBUG_RETURN(1);
table->table= dummy_table;
table->table->pos_in_table_list= table;
/*
Note: the table created above may be freed by:
1. JOIN_TAB::cleanup(), when the parent join is a regular join.
2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
degenerate join (e.g. one with "Impossible where").
*/
setup_table_map(table->table, table, table->jtbm_table_no);
} }
else else
{ {
DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION)); DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
subq_pred->is_jtbm_const_tab= FALSE; subq_pred->is_jtbm_const_tab= FALSE;
subselect_hash_sj_engine *hash_sj_engine= subselect_hash_sj_engine *hash_sj_engine=
((subselect_hash_sj_engine*)item->engine); ((subselect_hash_sj_engine*)subq_pred->engine);
table->table= hash_sj_engine->tmp_table; table->table= hash_sj_engine->tmp_table;
table->table->pos_in_table_list= table; table->table->pos_in_table_list= table;
setup_table_map(table->table, table, table->jtbm_table_no); setup_table_map(table->table, table, table->jtbm_table_no);
Item *sj_conds= hash_sj_engine->semi_join_conds; List_iterator<Item> li(*hash_sj_engine->semi_join_conds->argument_list());
Item *item;
(*join_where)= and_items(thd, *join_where, sj_conds); while ((item=li++))
if (!(*join_where)->fixed) {
(*join_where)->fix_fields(thd, join_where); if (eq_list.push_back(item, thd->mem_root))
DBUG_RETURN(TRUE);
}
} }
table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping); table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping);
} }
if ((nested_join= table->nested_join)) if ((nested_join= table->nested_join))
{ {
if (setup_jtbm_semi_joins(join, &nested_join->join_list, join_where)) if (setup_jtbm_semi_joins(join, &nested_join->join_list, eq_list))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
} }
@@ -5963,3 +6318,418 @@ bool JOIN::choose_tableless_subquery_plan()
} }
return FALSE; return FALSE;
} }
/*
Check if the item exists in the fields list of the left part of
the IN subquery predicate subq_pred and returns its corresponding
item from the select of the right part of subq_pred.
*/
Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred)
{
DBUG_ASSERT(type() == Item::FIELD_ITEM ||
(type() == Item::REF_ITEM &&
((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF));
List_iterator<Field_pair> it(subq_pred->corresponding_fields);
Field_pair *ret;
Item_field *field_item= (Item_field *) (real_item());
while ((ret= it++))
{
if (field_item->field == ret->field)
return ret->corresponding_item;
}
return NULL;
}
bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
return true;
if (item_equal)
{
Item_equal_fields_iterator it(*item_equal);
Item *equal_item;
while ((equal_item= it++))
{
if (equal_item->const_item())
continue;
if (equal_item->get_corresponding_field_in_insubq(subq_pred))
return true;
}
}
return false;
}
bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
return true;
}
return (*ref)->excl_dep_on_in_subq_left_part(subq_pred);
}
bool Item_equal::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
Item *left_item = get_const();
Item_equal_fields_iterator it(*this);
Item *item;
if (!left_item)
{
while ((item=it++))
{
if (item->excl_dep_on_in_subq_left_part(subq_pred))
{
left_item= item;
break;
}
}
}
if (!left_item)
return false;
while ((item=it++))
{
if (item->excl_dep_on_in_subq_left_part(subq_pred))
return true;
}
return false;
}
/**
@brief
Get corresponding item from the select of the right part of IN subquery
@param thd the thread handle
@param item the item from the left part of subq_pred for which
corresponding item should be found
@param subq_pred the IN subquery predicate
@details
This method looks through the fields of the select of the right part of
the IN subquery predicate subq_pred trying to find the corresponding
item 'new_item' for item. If item has equal items it looks through
the fields of the select of the right part of subq_pred for each equal
item trying to find the corresponding item.
The method assumes that the given item is either a field item or
a reference to a field item.
@retval <item*> reference to the corresponding item
@retval NULL if item was not found
*/
static
Item *get_corresponding_item(THD *thd, Item *item,
Item_in_subselect *subq_pred)
{
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
(item->type() == Item::REF_ITEM &&
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
Item *corresonding_item;
Item_equal *item_equal= item->get_item_equal();
if (item_equal)
{
Item_equal_fields_iterator it(*item_equal);
Item *equal_item;
while ((equal_item= it++))
{
corresonding_item=
equal_item->get_corresponding_field_in_insubq(subq_pred);
if (corresonding_item)
return corresonding_item;
}
return NULL;
}
else
return item->get_corresponding_field_in_insubq(subq_pred);
}
Item *Item_field::in_subq_field_transformer_for_where(THD *thd, uchar *arg)
{
Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
Item *producing_item= get_corresponding_item(thd, this, subq_pred);
if (producing_item)
return producing_item->build_clone(thd);
return this;
}
Item *Item_direct_view_ref::in_subq_field_transformer_for_where(THD *thd,
uchar *arg)
{
if (item_equal)
{
Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
Item *producing_item= get_corresponding_item(thd, this, subq_pred);
DBUG_ASSERT (producing_item != NULL);
return producing_item->build_clone(thd);
}
return this;
}
/**
@brief
Transforms item so it can be pushed into the IN subquery HAVING clause
@param thd the thread handle
@param in_item the item for which pushable item should be created
@param subq_pred the IN subquery predicate
@details
This method finds for in_item that is a field from the left part of the
IN subquery predicate subq_pred its corresponding item from the right part
of subq_pred.
If corresponding item is found, a shell for this item is created.
This shell can be pushed into the HAVING part of subq_pred select.
@retval <item*> reference to the created corresponding item shell for in_item
@retval NULL if mistake occurs
*/
static Item*
get_corresponding_item_for_in_subq_having(THD *thd, Item *in_item,
Item_in_subselect *subq_pred)
{
Item *new_item= get_corresponding_item(thd, in_item, subq_pred);
if (new_item)
{
Item_ref *ref=
new (thd->mem_root) Item_ref(thd,
&subq_pred->unit->first_select()->context,
NullS, NullS,
&new_item->name);
if (!ref)
DBUG_ASSERT(0);
return ref;
}
return new_item;
}
Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{
return get_corresponding_item_for_in_subq_having(thd, this,
(Item_in_subselect *)arg);
}
Item *Item_direct_view_ref::in_subq_field_transformer_for_having(THD *thd,
uchar *arg)
{
if (!item_equal)
return this;
else
{
Item *new_item= get_corresponding_item_for_in_subq_having(thd, this,
(Item_in_subselect *)arg);
if (!new_item)
return this;
return new_item;
}
}
/**
@brief
Find fields that are used in the GROUP BY of the select
@param thd the thread handle
@param sel the select of the IN subquery predicate
@param fields fields of the left part of the IN subquery predicate
@param grouping_list GROUP BY clause
@details
This method traverses fields which are used in the GROUP BY of
sel and saves them with their corresponding items from fields.
*/
bool grouping_fields_in_the_in_subq_left_part(THD *thd,
st_select_lex *sel,
List<Field_pair> *fields,
ORDER *grouping_list)
{
DBUG_ENTER("grouping_fields_in_the_in_subq_left_part");
sel->grouping_tmp_fields.empty();
List_iterator<Field_pair> it(*fields);
Field_pair *item;
while ((item= it++))
{
for (ORDER *ord= grouping_list; ord; ord= ord->next)
{
if ((*ord->item)->eq(item->corresponding_item, 0))
{
if (sel->grouping_tmp_fields.push_back(item, thd->mem_root))
DBUG_RETURN(TRUE);
}
}
}
DBUG_RETURN(FALSE);
}
/**
@brief
Extract condition that can be pushed into select of this IN subquery
@param thd the thread handle
@param cond current condition
@details
This function builds the most restrictive condition depending only on
the list of fields of the left part of this IN subquery predicate
(directly or indirectly through equality) that can be extracted from the
given condition cond and pushes it into this IN subquery.
Example of the transformation:
SELECT * FROM t1
WHERE a>3 AND b>10 AND
(a,b) IN (SELECT x,MAX(y) FROM t2 GROUP BY x);
=>
SELECT * FROM t1
WHERE a>3 AND b>10 AND
(a,b) IN (SELECT x,max(y)
FROM t2
WHERE x>3
GROUP BY x
HAVING MAX(y)>10);
In details:
1. Check what pushable formula can be extracted from cond
2. Build a clone PC of the formula that can be extracted
(the clone is built only if the extracted formula is a AND subformula
of cond or conjunction of such subformulas)
3. If there is no HAVING clause prepare PC to be conjuncted with
WHERE clause of this subquery. Otherwise do 4-7.
4. Check what formula PC_where can be extracted from PC to be pushed
into the WHERE clause of the subquery
5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC
getting PC_having
6. Prepare PC_where to be conjuncted with the WHERE clause of
the IN subquery
7. Prepare PC_having to be conjuncted with the HAVING clause of
the IN subquery
@note
This method is similar to pushdown_cond_for_derived()
@retval TRUE if an error occurs
@retval FALSE otherwise
*/
bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond)
{
DBUG_ENTER("Item_in_subselect::pushdown_cond_for_in_subquery");
Item *remaining_cond= NULL;
if (!cond)
DBUG_RETURN(FALSE);
st_select_lex *sel = unit->first_select();
if (is_jtbm_const_tab)
DBUG_RETURN(FALSE);
if (!sel->cond_pushdown_is_allowed())
DBUG_RETURN(FALSE);
/*
Create a list of Field_pair items for this IN subquery.
It consists of the pairs of fields from the left part of this IN subquery
predicate 'left_part' and the respective fields from the select of the
right part of the IN subquery 'sel' (the field from left_part with the
corresponding field from the sel projection list).
Attach this list to the IN subquery.
*/
corresponding_fields.empty();
List_iterator_fast<Item> it(sel->join->fields_list);
Item *item;
for (uint i= 0; i < left_expr->cols(); i++)
{
item= it++;
Item *elem= left_expr->element_index(i);
if (elem->real_item()->type() != Item::FIELD_ITEM)
continue;
if (corresponding_fields.push_back(
new Field_pair(((Item_field *)(elem->real_item()))->field,
item)))
DBUG_RETURN(TRUE);
}
/* 1. Check what pushable formula can be extracted from cond */
Item *extracted_cond;
cond->check_pushable_cond(&Item::pushable_cond_checker_for_subquery,
(uchar *)this);
/* 2. Build a clone PC of the formula that can be extracted */
extracted_cond=
cond->build_pushable_cond(thd,
&Item::pushable_equality_checker_for_subquery,
(uchar *)this);
/* Nothing to push */
if (!extracted_cond)
{
DBUG_RETURN(FALSE);
}
/* Collect fields that are used in the GROUP BY of sel */
st_select_lex *save_curr_select= thd->lex->current_select;
if (sel->have_window_funcs())
{
if (sel->group_list.first || sel->join->implicit_grouping)
goto exit;
ORDER *common_partition_fields=
sel->find_common_window_func_partition_fields(thd);
if (!common_partition_fields)
goto exit;
if (grouping_fields_in_the_in_subq_left_part(thd, sel, &corresponding_fields,
common_partition_fields))
DBUG_RETURN(TRUE);
}
else if (grouping_fields_in_the_in_subq_left_part(thd, sel,
&corresponding_fields,
sel->group_list.first))
DBUG_RETURN(TRUE);
/* Do 4-6 */
sel->pushdown_cond_into_where_clause(thd, extracted_cond,
&remaining_cond,
&Item::in_subq_field_transformer_for_where,
(uchar *) this);
if (!remaining_cond)
goto exit;
/*
7. Prepare PC_having to be conjuncted with the HAVING clause of
the IN subquery
*/
remaining_cond=
remaining_cond->transform(thd,
&Item::in_subq_field_transformer_for_having,
(uchar *)this);
if (!remaining_cond)
goto exit;
remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
0, 0);
sel->cond_pushed_into_having= remaining_cond;
exit:
thd->lex->current_select= save_curr_select;
DBUG_RETURN(FALSE);
}

View File

@@ -26,8 +26,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
bool convert_join_subqueries_to_semijoins(JOIN *join); bool convert_join_subqueries_to_semijoins(JOIN *join);
int pull_out_semijoin_tables(JOIN *join); int pull_out_semijoin_tables(JOIN *join);
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map); bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
COND_EQUAL **cond_eq,
List<Item> &new_conds,
Item::cond_result *cond_value);
bool setup_degenerate_jtbm_semi_joins(JOIN *join,
List<TABLE_LIST> *join_list,
List<Item> &eq_list);
bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list, bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
Item **join_where); List<Item> &eq_list);
void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list); void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list);
// used by Loose_scan_opt // used by Loose_scan_opt

View File

@@ -1242,25 +1242,61 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
/** /**
@brief @brief
Extract the condition depended on derived table/view and pushed it there Extract condition that can be pushed into a derived table/view
@param thd The thread handle @param thd the thread handle
@param cond The condition from which to extract the pushed condition @param cond current condition
@param derived The reference to the derived table/view @param derived the reference to the derived table/view
@details @details
This functiom builds the most restrictive condition depending only on This function builds the most restrictive condition depending only on
the derived table/view that can be extracted from the condition cond. the derived table/view (directly or indirectly through equality) that
The built condition is pushed into the having clauses of the can be extracted from the given condition cond and pushes it into the
selects contained in the query specifying the derived table/view. derived table/view.
The function also checks for each select whether any condition depending
only on grouping fields can be extracted from the pushed condition.
If so, it pushes the condition over grouping fields into the where
clause of the select.
@retval Example of the transformation:
true if an error is reported
false otherwise SELECT *
FROM t1,
(
SELECT x,MAX(y) AS max_y
FROM t2
GROUP BY x
) AS d_tab
WHERE d_tab.x>1 AND d_tab.max_y<30;
=>
SELECT *
FROM t1,
(
SELECT x,z,MAX(y) AS max_y
FROM t2
WHERE x>1
HAVING max_y<30
GROUP BY x
) AS d_tab
WHERE d_tab.x>1 AND d_tab.max_y<30;
In details:
1. Check what pushable formula can be extracted from cond
2. Build a clone PC of the formula that can be extracted
(the clone is built only if the extracted formula is a AND subformula
of cond or conjunction of such subformulas)
Do for every select specifying derived table/view:
3. If there is no HAVING clause prepare PC to be conjuncted with
WHERE clause of the select. Otherwise do 4-7.
4. Check what formula PC_where can be extracted from PC to be pushed
into the WHERE clause of the select
5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC
getting PC_having
6. Prepare PC_where to be conjuncted with the WHERE clause of the select
7. Prepare PC_having to be conjuncted with the HAVING clause of the select
@note
This method is similar to pushdown_cond_for_in_subquery()
@retval TRUE if an error occurs
@retval FALSE otherwise
*/ */
bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived) bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
@@ -1300,63 +1336,25 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!some_select_allows_cond_pushdown) if (!some_select_allows_cond_pushdown)
DBUG_RETURN(false); DBUG_RETURN(false);
/* /* 1. Check what pushable formula can be extracted from cond */
Build the most restrictive condition extractable from 'cond'
that can be pushed into the derived table 'derived'.
All subexpressions of this condition are cloned from the
subexpressions of 'cond'.
This condition has to be fixed yet.
*/
Item *extracted_cond; Item *extracted_cond;
derived->check_pushable_cond_for_table(cond); cond->check_pushable_cond(&Item::pushable_cond_checker_for_derived,
extracted_cond= derived->build_pushable_cond_for_table(thd, cond); (uchar *)(&derived->table->map));
/* 2. Build a clone PC of the formula that can be extracted */
extracted_cond=
cond->build_pushable_cond(thd,
&Item::pushable_equality_checker_for_derived,
((uchar *)&derived->table->map));
if (!extracted_cond) if (!extracted_cond)
{ {
/* Nothing can be pushed into the derived table */ /* Nothing can be pushed into the derived table */
DBUG_RETURN(false); DBUG_RETURN(false);
} }
/* Push extracted_cond into every select of the unit specifying 'derived' */
st_select_lex *save_curr_select= thd->lex->current_select; st_select_lex *save_curr_select= thd->lex->current_select;
for (; sl; sl= sl->next_select()) for (; sl; sl= sl->next_select())
{ {
Item *extracted_cond_copy; Item *extracted_cond_copy;
if (!sl->cond_pushdown_is_allowed())
continue;
thd->lex->current_select= sl;
if (sl->have_window_funcs())
{
if (sl->join->group_list || sl->join->implicit_grouping)
continue;
ORDER *common_partition_fields=
sl->find_common_window_func_partition_fields(thd);
if (!common_partition_fields)
continue;
extracted_cond_copy= !sl->next_select() ?
extracted_cond :
extracted_cond->build_clone(thd);
if (!extracted_cond_copy)
continue;
Item *cond_over_partition_fields;;
sl->collect_grouping_fields(thd, common_partition_fields);
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
derived);
cond_over_partition_fields=
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
if (cond_over_partition_fields)
cond_over_partition_fields= cond_over_partition_fields->transform(thd,
&Item::derived_grouping_field_transformer_for_where,
(uchar*) sl);
if (cond_over_partition_fields)
{
cond_over_partition_fields->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
sl->cond_pushed_into_where= cond_over_partition_fields;
}
continue;
}
/* /*
For each select of the unit except the last one For each select of the unit except the last one
create a clone of extracted_cond create a clone of extracted_cond
@@ -1367,73 +1365,44 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!extracted_cond_copy) if (!extracted_cond_copy)
continue; continue;
if (!sl->join->group_list && !sl->with_sum_func) /* Collect fields that are used in the GROUP BY of sl */
if (sl->have_window_funcs())
{ {
/* extracted_cond_copy is pushed into where of sl */ if (sl->group_list.first || sl->join->implicit_grouping)
extracted_cond_copy= extracted_cond_copy->transform(thd, continue;
ORDER *common_partition_fields=
sl->find_common_window_func_partition_fields(thd);
if (!common_partition_fields)
continue;
sl->collect_grouping_fields(thd, common_partition_fields);
}
else
sl->collect_grouping_fields(thd, sl->group_list.first);
Item *remaining_cond= NULL;
/* Do 4-6 */
sl->pushdown_cond_into_where_clause(thd, extracted_cond_copy,
&remaining_cond,
&Item::derived_field_transformer_for_where, &Item::derived_field_transformer_for_where,
(uchar *) sl); (uchar *) sl);
if (extracted_cond_copy)
{
extracted_cond_copy->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
sl->cond_pushed_into_where= extracted_cond_copy;
}
if (!remaining_cond)
continue; continue;
}
/* /*
Figure out what can be extracted from the pushed condition 7. Prepare PC_having to be conjuncted with the HAVING clause of
that could be pushed into the where clause of sl the select
*/ */
Item *cond_over_grouping_fields; remaining_cond=
sl->collect_grouping_fields(thd, sl->join->group_list); remaining_cond->transform(thd,
sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
derived);
cond_over_grouping_fields=
sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
/*
Transform the references to the 'derived' columns from the condition
pushed into the where clause of sl to make them usable in the new context
*/
if (cond_over_grouping_fields)
cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
&Item::derived_grouping_field_transformer_for_where,
(uchar*) sl);
if (cond_over_grouping_fields)
{
/*
In extracted_cond_copy remove top conjuncts that
has been pushed into the where clause of sl
*/
extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
cond_over_grouping_fields->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
sl->cond_pushed_into_where= cond_over_grouping_fields;
if (!extracted_cond_copy)
continue;
}
/*
Transform the references to the 'derived' columns from the condition
pushed into the having clause of sl to make them usable in the new context
*/
extracted_cond_copy= extracted_cond_copy->transform(thd,
&Item::derived_field_transformer_for_having, &Item::derived_field_transformer_for_having,
(uchar *) sl); (uchar *) sl);
if (!extracted_cond_copy) if (!remaining_cond)
continue; continue;
extracted_cond_copy->walk(&Item::cleanup_excluding_const_fields_processor, remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
0, 0); 0, 0);
sl->cond_pushed_into_having= extracted_cond_copy; sl->cond_pushed_into_having= remaining_cond;
} }
thd->lex->current_select= save_curr_select; thd->lex->current_select= save_curr_select;
DBUG_RETURN(false); DBUG_RETURN(false);
} }

View File

@@ -7245,8 +7245,8 @@ void st_select_lex::collect_grouping_fields(THD *thd,
{ {
if ((*ord->item)->eq((Item*)item, 0)) if ((*ord->item)->eq((Item*)item, 0))
{ {
Grouping_tmp_field *grouping_tmp_field= Field_pair *grouping_tmp_field=
new Grouping_tmp_field(master_unit()->derived->table->field[i], item); new Field_pair(master_unit()->derived->table->field[i], item);
grouping_tmp_fields.push_back(grouping_tmp_field); grouping_tmp_fields.push_back(grouping_tmp_field);
} }
} }
@@ -7277,8 +7277,7 @@ void st_select_lex::collect_grouping_fields(THD *thd,
*/ */
void void
st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond, st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
TABLE_LIST *derived)
{ {
cond->clear_extraction_flag(); cond->clear_extraction_flag();
if (cond->type() == Item::COND_ITEM) if (cond->type() == Item::COND_ITEM)
@@ -7291,7 +7290,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
Item *item; Item *item;
while ((item=li++)) while ((item=li++))
{ {
check_cond_extraction_for_grouping_fields(item, derived); check_cond_extraction_for_grouping_fields(item);
if (item->get_extraction_flag() != NO_EXTRACTION_FL) if (item->get_extraction_flag() != NO_EXTRACTION_FL)
{ {
count++; count++;
@@ -7340,7 +7339,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
to figure out whether a subformula depends only on these fields or not. to figure out whether a subformula depends only on these fields or not.
@note @note
The built condition C is always implied by the condition cond The built condition C is always implied by the condition cond
(cond => C). The method tries to build the most restictive such (cond => C). The method tries to build the least restictive such
condition (i.e. for any other condition C' such that cond => C' condition (i.e. for any other condition C' such that cond => C'
we have C => C'). we have C => C').
@note @note
@@ -7757,3 +7756,128 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const
make_item_func_trim_oracle(thd) : make_item_func_trim_oracle(thd) :
make_item_func_trim_std(thd); make_item_func_trim_std(thd);
} }
/**
@brief
Extract from given item a condition pushable into WHERE clause
@param thd the thread handle
@param cond the item to extract a condition to be pushed
into WHERE
@param remaining_cond the condition that will remain of cond after
the pushdown of its parts into the WHERE clause
@param transformer the transformer callback function to be
applied to the condition so it can be pushed
down into the WHERE clause of this select
@param arg parameter to be passed to the transformer
@details
This method checks if cond entirely or its parts can be
pushed into the WHERE clause of this select and prepares it for pushing.
First it checks wherever this select doesn't have any aggregation function
in its projection and GROUP BY clause. If so cond can be entirely
pushed into the WHERE clause of this select but before its fields should
be transformed with transformer_for_where to make it pushable.
Otherwise the method checks wherever any condition depending only on
grouping fields can be extracted from cond. If there is any it prepares it
for pushing using grouping_field_transformer_for_where and if it happens to
be a conjunct of cond it removes it from cond. It saves the result of
removal in remaining_cond.
The extracted condition is saved in cond_pushed_into_where of this select.
@note
When looking for pushable condition the method considers only the grouping
fields from the list grouping_tmp_fields whose elements are of the type
Field_pair. This list must be prepared before the call of the
function.
@note
This method is called for pushdown conditions into materialized
derived tables/views optimization.
Item::derived_field_transformer_for_where is passed as the actual
callback function.
Also it is called for pushdown conditions into materialized IN subqueries.
Item::in_subq_field_transformer_for_where is passed as the actual
callback function.
*/
void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
Item **remaining_cond,
Item_transformer transformer,
uchar *arg)
{
if (!cond_pushdown_is_allowed())
return;
thd->lex->current_select= this;
if (have_window_funcs())
{
Item *cond_over_partition_fields;
check_cond_extraction_for_grouping_fields(cond);
cond_over_partition_fields=
build_cond_for_grouping_fields(thd, cond, true);
if (cond_over_partition_fields)
cond_over_partition_fields= cond_over_partition_fields->transform(thd,
&Item::grouping_field_transformer_for_where,
(uchar*) this);
if (cond_over_partition_fields)
{
cond_over_partition_fields->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
cond_pushed_into_where= cond_over_partition_fields;
}
return;
}
if (!join->group_list && !with_sum_func)
{
cond=
cond->transform(thd, transformer, arg);
if (cond)
{
cond->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
cond_pushed_into_where= cond;
}
return;
}
/*
Figure out what can be extracted from cond
that could be pushed into the WHERE clause of this select
*/
Item *cond_over_grouping_fields;
check_cond_extraction_for_grouping_fields(cond);
cond_over_grouping_fields=
build_cond_for_grouping_fields(thd, cond, true);
/*
Transform the references to the columns from the cond
pushed into the WHERE clause of this select to make them usable in
the new context
*/
if (cond_over_grouping_fields)
cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
&Item::grouping_field_transformer_for_where,
(uchar*) this);
if (cond_over_grouping_fields)
{
/*
In cond remove top conjuncts that has been pushed into the WHERE
clause of this select
*/
cond= remove_pushed_top_conjuncts(thd, cond);
cond_over_grouping_fields->walk(
&Item::cleanup_excluding_const_fields_processor, 0, 0);
cond_pushed_into_where= cond_over_grouping_fields;
}
*remaining_cond= cond;
}

View File

@@ -808,19 +808,19 @@ typedef Bounds_checked_array<Item*> Ref_ptr_array;
/* /*
Structure which consists of the field and the item which Structure which consists of the field and the item that
produces this field. corresponds to this field.
*/ */
class Field_pair :public Sql_alloc
class Grouping_tmp_field :public Sql_alloc
{ {
public: public:
Field *tmp_field; Field *field;
Item *producing_item; Item *corresponding_item;
Grouping_tmp_field(Field *fld, Item *item) Field_pair(Field *fld, Item *item)
:tmp_field(fld), producing_item(item) {} :field(fld), corresponding_item(item) {}
}; };
/* /*
SELECT_LEX - store information of parsed SELECT statment SELECT_LEX - store information of parsed SELECT statment
*/ */
@@ -1033,7 +1033,8 @@ public:
nesting_map name_visibility_map; nesting_map name_visibility_map;
table_map with_dep; table_map with_dep;
List<Grouping_tmp_field> grouping_tmp_fields; /* the structure to store fields that are used in the GROUP BY of this select */
List<Field_pair> grouping_tmp_fields;
/* it is for correct printing SELECT options */ /* it is for correct printing SELECT options */
thr_lock_type lock_type; thr_lock_type lock_type;
@@ -1239,8 +1240,7 @@ public:
bool check_unrestricted_recursive(bool only_standard_compliant); bool check_unrestricted_recursive(bool only_standard_compliant);
bool check_subqueries_with_recursive_references(); bool check_subqueries_with_recursive_references();
void collect_grouping_fields(THD *thd, ORDER *grouping_list); void collect_grouping_fields(THD *thd, ORDER *grouping_list);
void check_cond_extraction_for_grouping_fields(Item *cond, void check_cond_extraction_for_grouping_fields(Item *cond);
TABLE_LIST *derived);
Item *build_cond_for_grouping_fields(THD *thd, Item *cond, Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
bool no_to_clones); bool no_to_clones);
@@ -1266,6 +1266,11 @@ public:
bool cond_pushdown_is_allowed() const bool cond_pushdown_is_allowed() const
{ return !olap && !explicit_limit && !tvc; } { return !olap && !explicit_limit && !tvc; }
void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond,
Item **remaining_cond,
Item_transformer transformer,
uchar *arg);
private: private:
bool m_non_agg_field_used; bool m_non_agg_field_used;
bool m_agg_func_used; bool m_agg_func_used;

View File

@@ -228,6 +228,7 @@
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29) #define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30) #define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31) #define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -254,7 +255,8 @@
OPTIMIZER_SWITCH_EXISTS_TO_IN | \ OPTIMIZER_SWITCH_EXISTS_TO_IN | \
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \ OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED) OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)
/* /*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you Replication uses 8 bytes to store SQL_MODE in the binary log. The day you

View File

@@ -1617,9 +1617,28 @@ JOIN::optimize_inner()
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
} }
if (setup_jtbm_semi_joins(this, join_list, &conds)) List<Item> eq_list;
if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
DBUG_RETURN(1); DBUG_RETURN(1);
if (eq_list.elements != 0)
{
Item *new_cond;
if (eq_list.elements == 1)
new_cond= eq_list.pop();
else
new_cond= new (thd->mem_root) Item_cond_and(thd, eq_list);
if (new_cond &&
((new_cond->fix_fields(thd, &new_cond) ||
!(conds= and_items(thd, conds, new_cond)) ||
conds->fix_fields(thd, &conds))))
DBUG_RETURN(TRUE);
}
eq_list.empty();
if (select_lex->cond_pushed_into_where) if (select_lex->cond_pushed_into_where)
{ {
conds= and_conds(thd, conds, select_lex->cond_pushed_into_where); conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
@@ -1641,6 +1660,32 @@ JOIN::optimize_inner()
conds= optimize_cond(this, conds, join_list, FALSE, conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS); &cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
if (thd->lex->sql_command == SQLCOM_SELECT &&
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
{
TABLE_LIST *tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
while ((tbl= li++))
if (tbl->jtbm_subselect)
{
if (tbl->jtbm_subselect->pushdown_cond_for_in_subquery(thd, conds))
DBUG_RETURN(1);
}
}
if (setup_jtbm_semi_joins(this, join_list, eq_list))
DBUG_RETURN(1);
if (eq_list.elements != 0)
{
conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
eq_list, &cond_value);
if (!conds &&
cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
DBUG_RETURN(TRUE);
}
if (thd->lex->sql_command == SQLCOM_SELECT && if (thd->lex->sql_command == SQLCOM_SELECT &&
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED)) optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{ {
@@ -1679,7 +1724,6 @@ JOIN::optimize_inner()
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE)) if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (thd->is_error()) if (thd->is_error())
{ {
error= 1; error= 1;
@@ -13382,7 +13426,7 @@ finish:
FALSE otherwise FALSE otherwise
*/ */
static bool check_simple_equality(THD *thd, const Item::Context &ctx, bool check_simple_equality(THD *thd, const Item::Context &ctx,
Item *left_item, Item *right_item, Item *left_item, Item *right_item,
COND_EQUAL *cond_equal) COND_EQUAL *cond_equal)
{ {

View File

@@ -1470,6 +1470,11 @@ public:
Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting; Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting;
JOIN_TAB *sort_and_group_aggr_tab; JOIN_TAB *sort_and_group_aggr_tab;
/*
Flag is set to true if select_lex was found to be degenerated before
the optimize_cond() call in JOIN::optimize_inner() method.
*/
bool is_orig_degenerated;
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg, JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg) select_result *result_arg)
@@ -1564,6 +1569,7 @@ public:
emb_sjm_nest= NULL; emb_sjm_nest= NULL;
sjm_lookup_tables= 0; sjm_lookup_tables= 0;
sjm_scan_tables= 0; sjm_scan_tables= 0;
is_orig_degenerated= false;
} }
/* True if the plan guarantees that it will be returned zero or one row */ /* True if the plan guarantees that it will be returned zero or one row */
@@ -1734,6 +1740,7 @@ public:
bool fix_all_splittings_in_plan(); bool fix_all_splittings_in_plan();
bool transform_in_predicates_into_in_subq(THD *thd); bool transform_in_predicates_into_in_subq(THD *thd);
bool add_equalities_to_where_condition(THD *thd, List<Item> &eq_list);
private: private:
/** /**
Create a temporary table to be used for processing DISTINCT/ORDER Create a temporary table to be used for processing DISTINCT/ORDER
@@ -2325,7 +2332,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
extern bool test_if_ref(Item *, extern bool test_if_ref(Item *,
Item_field *left_item,Item *right_item); Item_field *left_item,Item *right_item);
inline bool optimizer_flag(THD *thd, uint flag) inline bool optimizer_flag(THD *thd, ulonglong flag)
{ {
return (thd->variables.optimizer_switch & flag); return (thd->variables.optimizer_switch & flag);
} }
@@ -2440,4 +2447,13 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort);
JOIN_TAB *first_explain_order_tab(JOIN* join); JOIN_TAB *first_explain_order_tab(JOIN* join);
JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab); JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab);
bool check_simple_equality(THD *thd, const Item::Context &ctx,
Item *left_item, Item *right_item,
COND_EQUAL *cond_equal);
void propagate_new_equalities(THD *thd, Item *cond,
List<Item_equal> *new_equalities,
COND_EQUAL *inherited,
bool *is_simplifiable_cond);
#endif /* SQL_SELECT_INCLUDED */ #endif /* SQL_SELECT_INCLUDED */

View File

@@ -2472,6 +2472,7 @@ export const char *optimizer_switch_names[]=
"orderby_uses_equalities", "orderby_uses_equalities",
"condition_pushdown_for_derived", "condition_pushdown_for_derived",
"split_materialized", "split_materialized",
"condition_pushdown_for_subquery",
"default", "default",
NullS NullS
}; };

View File

@@ -8315,200 +8315,6 @@ double KEY::actual_rec_per_key(uint i)
} }
/**
@brief
Mark subformulas of a condition unusable for the condition pushed into table
@param cond The condition whose subformulas are to be marked
@details
This method recursively traverses the AND-OR condition cond and for each subformula
of the codition it checks whether it can be usable for the extraction of a condition
that can be pushed into this table. The subformulas that are not usable are
marked with the flag NO_EXTRACTION_FL.
@note
This method is called before any call of TABLE_LIST::build_pushable_cond_for_table.
The flag NO_EXTRACTION_FL set in a subformula allows to avoid building clone
for the subformula when extracting the pushable condition.
*/
void TABLE_LIST::check_pushable_cond_for_table(Item *cond)
{
table_map tab_map= table->map;
cond->clear_extraction_flag();
if (cond->type() == Item::COND_ITEM)
{
bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
uint count= 0;
Item *item;
while ((item=li++))
{
check_pushable_cond_for_table(item);
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
count++;
else if (!and_cond)
break;
}
if ((and_cond && count == 0) || item)
{
cond->set_extraction_flag(NO_EXTRACTION_FL);
if (and_cond)
li.rewind();
while ((item= li++))
item->clear_extraction_flag();
}
}
else if (!cond->excl_dep_on_table(tab_map))
cond->set_extraction_flag(NO_EXTRACTION_FL);
}
/**
@brief
Build condition extractable from the given one depended only on this table
@param thd The thread handle
@param cond The condition from which the pushable one is to be extracted
@details
For the given condition cond this method finds out what condition depended
only on this table can be extracted from cond. If such condition C exists
the method builds the item for it.
The method uses the flag NO_EXTRACTION_FL set by the preliminary call of
the method TABLE_LIST::check_pushable_cond_for_table to figure out whether
a subformula depends only on this table or not.
@note
The built condition C is always implied by the condition cond
(cond => C). The method tries to build the most restictive such
condition (i.e. for any other condition C' such that cond => C'
we have C => C').
@note
The build item is not ready for usage: substitution for the field items
has to be done and it has to be re-fixed.
@retval
the built condition pushable into this table if such a condition exists
NULL if there is no such a condition
*/
Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond)
{
table_map tab_map= table->map;
bool is_multiple_equality= cond->type() == Item::FUNC_ITEM &&
((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC;
if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
return 0;
if (cond->type() == Item::COND_ITEM)
{
bool cond_and= false;
Item_cond *new_cond;
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
cond_and= true;
new_cond=new (thd->mem_root) Item_cond_and(thd);
}
else
new_cond= new (thd->mem_root) Item_cond_or(thd);
if (!new_cond)
return 0;
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
bool is_fix_needed= false;
while ((item=li++))
{
if (item->get_extraction_flag() == NO_EXTRACTION_FL)
{
if (!cond_and)
return 0;
continue;
}
Item *fix= build_pushable_cond_for_table(thd, item);
if (!fix && !cond_and)
return 0;
if (!fix)
continue;
if (fix->type() == Item::COND_ITEM &&
((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
is_fix_needed= true;
new_cond->argument_list()->push_back(fix, thd->mem_root);
}
if (is_fix_needed)
new_cond->fix_fields(thd, 0);
switch (new_cond->argument_list()->elements)
{
case 0:
return 0;
case 1:
return new_cond->argument_list()->head();
default:
return new_cond;
}
}
else if (is_multiple_equality)
{
if (!(cond->used_tables() & tab_map))
return 0;
Item *new_cond= NULL;
int i= 0;
Item_equal *item_equal= (Item_equal *) cond;
Item *left_item = item_equal->get_const();
Item_equal_fields_iterator it(*item_equal);
Item *item;
if (!left_item)
{
while ((item=it++))
if (item->used_tables() == tab_map)
{
left_item= item;
break;
}
}
if (!left_item)
return 0;
while ((item=it++))
{
if (!(item->used_tables() == tab_map))
continue;
Item_func_eq *eq= 0;
Item *left_item_clone= left_item->build_clone(thd);
Item *right_item_clone= item->build_clone(thd);
if (left_item_clone && right_item_clone)
{
left_item_clone->set_item_equal(NULL);
right_item_clone->set_item_equal(NULL);
eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
left_item_clone);
}
if (eq)
{
i++;
switch (i)
{
case 1:
new_cond= eq;
break;
case 2:
new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
break;
default:
((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
thd->mem_root);
}
}
}
if (new_cond)
new_cond->fix_fields(thd, &new_cond);
return new_cond;
}
else if (cond->get_extraction_flag() != NO_EXTRACTION_FL)
return cond->build_clone(thd);
return 0;
}
LEX_CSTRING *fk_option_name(enum_fk_option opt) LEX_CSTRING *fk_option_name(enum_fk_option opt)
{ {
static LEX_CSTRING names[]= static LEX_CSTRING names[]=

View File

@@ -2595,8 +2595,6 @@ struct TABLE_LIST
return false; return false;
} }
void set_lock_type(THD* thd, enum thr_lock_type lock); void set_lock_type(THD* thd, enum thr_lock_type lock);
void check_pushable_cond_for_table(Item *cond);
Item *build_pushable_cond_for_table(THD *thd, Item *cond);
private: private:
bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_check_option(THD *thd, uint8 check_opt_type);

View File

@@ -1,7 +1,7 @@
drop table if exists t; drop table if exists t;
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb; create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4); insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0; explain select x,id from t force index (x) where x=0 and id=0;

View File

@@ -1,7 +1,7 @@
drop table if exists t; drop table if exists t;
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb; create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=tokudb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4); insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0; explain select x,id from t force index (x) where x=0 and id=0;

View File

@@ -1,7 +1,7 @@
drop table if exists t; drop table if exists t;
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb; create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1); insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1; explain select c,a,b from t where c=0 and a=0 and b=1;

View File

@@ -1,7 +1,7 @@
drop table if exists t; drop table if exists t;
select @@optimizer_switch; select @@optimizer_switch;
@@optimizer_switch @@optimizer_switch
index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb; create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=tokudb;
insert into t values (0,0,0,0),(0,1,0,1); insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1; explain select c,a,b from t where c=0 and a=0 and b=1;