Skip to content

Commit

Permalink
MDEV-7487 Semi-join optimization for single-table update/delete state…
Browse files Browse the repository at this point in the history
…ments

This patch allows to use semi-join optimization at the top level of
single-table update and delete statements.
The problem of supporting such optimization became easy to resolve after
processing a single-table update/delete statement started using JOIN
structure. This allowed to use JOIN::prepare() not only for multi-table
updates/deletes but for single-table ones as well. This was done in the
patch for mdev-28883:
Re-design the upper level of handling UPDATE and DELETE statements.

Note that JOIN::prepare() detects all subqueries that can be considered
as candidates for semi-join optimization. The code added by this patch
looks for such candidates at the top level and if such candidates are found
in the processed single-table update/delete the statement is handled in
the same way as a multi-table update/delete.

    Approved by Oleksandr Byelkin <sanja@mariadb.com>
  • Loading branch information
igorbabaev committed Mar 16, 2023
1 parent e2e3524 commit 554278e
Show file tree
Hide file tree
Showing 14 changed files with 6,198 additions and 35 deletions.
2,409 changes: 2,409 additions & 0 deletions mysql-test/main/delete_single_to_multi.result

Large diffs are not rendered by default.

801 changes: 801 additions & 0 deletions mysql-test/main/delete_single_to_multi.test

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion mysql-test/main/log_state.result
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ rows_examined sql_text
4 UPDATE t1 SET a=a+sleep(.02) WHERE a>2
8 UPDATE t1 SET a=a+sleep(.02) ORDER BY a DESC
1 UPDATE t2 set b=b+sleep(.02) limit 1
4 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
10 UPDATE t1 SET a=a+sleep(.02) WHERE a in (SELECT b from t2)
6 DELETE FROM t1 WHERE a=a+sleep(.02) ORDER BY a LIMIT 2
disconnect con2;
connection default;
Expand Down
45 changes: 25 additions & 20 deletions mysql-test/main/myisam_explain_non_select_all.result
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,16 @@ INSERT INTO t2 VALUES (1), (2), (3);
#
EXPLAIN UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 Using where
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE 1 IN (SELECT 1 FROM t2 WHERE t2.b < 3);
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
2 SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00 Using where
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
Expand All @@ -246,8 +248,9 @@ Handler_read_key 4
Handler_read_rnd_next 5
# Status of testing query execution:
Variable_name Value
Handler_read_key 4
Handler_read_rnd_next 5
Handler_read_key 5
Handler_read_rnd 3
Handler_read_rnd_next 12
Handler_update 3

DROP TABLE t1, t2;
Expand All @@ -263,13 +266,13 @@ INSERT INTO t2 VALUES (1), (2), (3);
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT b FROM t2 WHERE t1.a < 3);
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
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 3 100.00 Using where
1 PRIMARY t2 ALL NULL NULL NULL NULL 3 100.00 Using where; FirstMatch(t1)
Warnings:
Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1
# Status of EXPLAIN EXTENDED query
Expand Down Expand Up @@ -900,14 +903,16 @@ INSERT INTO t2 VALUES (1), (2), (3), (1000);
#
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 Using where
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT a FROM t2);
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
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 4 100.00 Using where
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 100.00
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 100.00
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 3 100.00
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
Expand All @@ -928,8 +933,8 @@ Handler_read_key 4
Handler_read_rnd_next 9
# Status of testing query execution:
Variable_name Value
Handler_read_key 4
Handler_read_rnd_next 10
Handler_read_key 7
Handler_read_rnd_next 8
Handler_update 3

DROP TABLE t1, t2;
Expand Down Expand Up @@ -986,14 +991,14 @@ INSERT INTO t1 VALUES (1), (2), (3), (4), (5);
#
EXPLAIN DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 Using where
1 PRIMARY t1 ALL NULL NULL NULL NULL 5
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 Using where; FirstMatch(t1)
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED DELETE FROM t1 WHERE a1 IN (SELECT a2 FROM t2 WHERE a2 > 2);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00 Using where
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 5 100.00 Using where
1 PRIMARY t1 ALL NULL NULL NULL NULL 5 100.00
1 PRIMARY t2 ALL NULL NULL NULL NULL 5 100.00 Using where; FirstMatch(t1)
# Status of EXPLAIN EXTENDED query
Variable_name Value
Handler_read_key 4
Expand Down Expand Up @@ -2823,14 +2828,14 @@ INSERT INTO t2 VALUES (1), (2), (3);
EXPLAIN UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where
2 DEPENDENT SUBQUERY <derived3> unique_subquery distinct_key distinct_key 5 func 1
1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 Using filesort
FLUSH STATUS;
FLUSH TABLES;
EXPLAIN EXTENDED UPDATE t1 SET a = 10 WHERE a IN (SELECT * FROM (SELECT b FROM t2 ORDER BY b LIMIT 2,2) x);
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
2 DEPENDENT SUBQUERY <derived3> unique_subquery distinct_key distinct_key 5 func 1 100.00
1 PRIMARY <derived3> ref key0 key0 5 test.t1.a 2 100.00 FirstMatch(t1)
3 DERIVED t2 ALL NULL NULL NULL NULL 3 100.00 Using filesort
# Status of EXPLAIN EXTENDED query
Variable_name Value
Expand Down
20 changes: 20 additions & 0 deletions mysql-test/main/opt_trace.result
Original file line number Diff line number Diff line change
Expand Up @@ -4466,6 +4466,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
}
},
{
"table": "t0",
"rowid_filters": [
{
"key": "a",
"build_cost": 0.174715752,
"rows": 3
}
]
},
{
"selectivity_for_indexes": [
{
Expand Down Expand Up @@ -4531,6 +4541,16 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
}
}
},
{
"table": "t1",
"rowid_filters": [
{
"key": "a",
"build_cost": 0.174715752,
"rows": 3
}
]
},
{
"selectivity_for_indexes": [
{
Expand Down
6 changes: 3 additions & 3 deletions mysql-test/main/opt_trace_security.test
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ delimiter ;|

--change_user foo
set optimizer_trace="enabled=on";
# --error 1142
# select * from db1.t1;
# select * from information_schema.OPTIMIZER_TRACE;
--error 1142
select * from db1.t1;
select * from information_schema.OPTIMIZER_TRACE;
set optimizer_trace="enabled=off";

--change_user root
Expand Down
Loading

0 comments on commit 554278e

Please sign in to comment.