Skip to content

Commit 0b7339e

Browse files
committed
MDEV-17382 Hash join algorithm should not be used to join materialized
derived table / view by equality Now rows of a materialized derived table are always put into a temporary table before join operation. If BNLH is used to join this table with the result of a partial join then both operands of the join are actually put into main memory. In most cases this is not efficient. We could avoid this by sending the rows of the derived table directly to the join operation. However this kind of data flow is not supported yet. Fixed by not allowing usage of hash join algorithm to join a materialized derived table if it's joined by an equality predicate of the form f=e where f is a field of the derived table.
1 parent 9905949 commit 0b7339e

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

mysql-test/r/derived_opt.result

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,42 @@ where
499499
D1.a= t1.a;
500500
id select_type table type possible_keys key key_len ref rows Extra
501501
1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using where
502-
1 PRIMARY <derived2>hash_ALLkey0#hash#key0 5 test.t1.a100 Using join buffer (flat, BNLH join)
502+
1 PRIMARY <derived2>refkey0 key0 5 test.t1.a10
503503
2 DERIVED t2 ALL NULL NULL NULL NULL 100 Using filesort
504504
set join_cache_level=@tmp_jcl;
505505
set optimizer_switch=@tmp_os;
506506
drop table t1, t2;
507+
#
508+
# Bug mdev-17382: equi-join of derived table with join_cache_level=4
509+
#
510+
CREATE TABLE t1 (
511+
id int NOT NULL,
512+
amount decimal DEFAULT NULL,
513+
PRIMARY KEY (id)
514+
);
515+
CREATE TABLE t2 (
516+
id int NOT NULL,
517+
name varchar(50) DEFAULT NULL,
518+
PRIMARY KEY (id)
519+
);
520+
INSERT INTO t1 VALUES
521+
(1, 10.0000), (2, 20.0000), (3, 30.0000), (4, 40.0000),
522+
(5, NULL), (6, NULL), (7, 70.0000), (8, 80.0000);
523+
INSERT INTO t2 VALUES
524+
(1,'A'), (2,'B'), (3,'C'), (4,'D'), (5, NULL), (6, NULL),
525+
(7,'E'), (8,'F'), (9,'G'), (10,'H'), (11, NULL), (12, NULL);
526+
set join_cache_level=4;
527+
EXPLAIN
528+
SELECT t2.id,t2.name,t.total_amt
529+
FROM t2
530+
LEFT JOIN
531+
(SELECT id, sum(amount) total_amt FROM t1 GROUP BY id) AS t
532+
ON t2.id=t.id
533+
WHERE t2.id < 3;
534+
id select_type table type possible_keys key key_len ref rows Extra
535+
1 PRIMARY t2 range PRIMARY PRIMARY 4 NULL 3 Using index condition
536+
1 PRIMARY <derived2> ref key0 key0 5 test.t2.id 2
537+
2 DERIVED t1 ALL NULL NULL NULL NULL 8 Using temporary; Using filesort
538+
set join_cache_level=default;
539+
DROP TABLE t1,t2;
507540
set optimizer_switch=@exit_optimizer_switch;

mysql-test/r/innodb_mrr_cpk.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ set join_cache_level=3;
226226
explain SELECT 1 FROM (SELECT url, id FROM t2 LIMIT 1 OFFSET 20) derived RIGHT JOIN t1 ON t1.id = derived.id;
227227
id select_type table type possible_keys key key_len ref rows Extra
228228
1 PRIMARY t1 ALL NULL NULL NULL NULL #
229-
1 PRIMARY <derived2>hash_ALLkey0#hash#key0 25 test.t1.id #Using join buffer (flat, BNLH join)
229+
1 PRIMARY <derived2>refkey0 key0 25 test.t1.id #
230230
2 DERIVED t2 ALL NULL NULL NULL NULL #
231231
set join_cache_level= @tmp_mdev5037;
232232
drop table t0,t1,t2;

mysql-test/t/derived_opt.test

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,5 +363,43 @@ set join_cache_level=@tmp_jcl;
363363
set optimizer_switch=@tmp_os;
364364
drop table t1, t2;
365365

366+
--echo #
367+
--echo # Bug mdev-17382: equi-join of derived table with join_cache_level=4
368+
--echo #
369+
370+
CREATE TABLE t1 (
371+
id int NOT NULL,
372+
amount decimal DEFAULT NULL,
373+
PRIMARY KEY (id)
374+
);
375+
376+
CREATE TABLE t2 (
377+
id int NOT NULL,
378+
name varchar(50) DEFAULT NULL,
379+
PRIMARY KEY (id)
380+
);
381+
382+
INSERT INTO t1 VALUES
383+
(1, 10.0000), (2, 20.0000), (3, 30.0000), (4, 40.0000),
384+
(5, NULL), (6, NULL), (7, 70.0000), (8, 80.0000);
385+
386+
INSERT INTO t2 VALUES
387+
(1,'A'), (2,'B'), (3,'C'), (4,'D'), (5, NULL), (6, NULL),
388+
(7,'E'), (8,'F'), (9,'G'), (10,'H'), (11, NULL), (12, NULL);
389+
390+
set join_cache_level=4;
391+
392+
EXPLAIN
393+
SELECT t2.id,t2.name,t.total_amt
394+
FROM t2
395+
LEFT JOIN
396+
(SELECT id, sum(amount) total_amt FROM t1 GROUP BY id) AS t
397+
ON t2.id=t.id
398+
WHERE t2.id < 3;
399+
400+
set join_cache_level=default;
401+
402+
DROP TABLE t1,t2;
403+
366404
# The following command must be the last one the file
367405
set optimizer_switch=@exit_optimizer_switch;

sql/sql_select.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10054,7 +10054,15 @@ uint check_join_cache_usage(JOIN_TAB *tab,
1005410054
effort now.
1005510055
*/
1005610056
if (tab->table->pos_in_table_list->is_materialized_derived())
10057+
{
1005710058
no_bka_cache= true;
10059+
/*
10060+
Don't use hash join algorithm if the temporary table for the rows
10061+
of the derived table will be created with an equi-join key.
10062+
*/
10063+
if (tab->table->s->keys)
10064+
no_hashed_cache= true;
10065+
}
1005810066

1005910067
/*
1006010068
Don't use join buffering if we're dictated not to by no_jbuf_after

0 commit comments

Comments
 (0)