Bug #30584: delete with order by and limit clauses does not
use limit efficiently
Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a
filesort even if not required
Also two bugs reported after QA review (before the commit
of bugs above to public trees, no documentation needed):
Bug #53737: Performance regressions after applying patch
for bug 36569
Bug #53742: UPDATEs have no effect after applying patch
for bug 36569
Execution of single-table UPDATE and DELETE statements did not use the
same optimizer as was used in the compilation of SELECT statements.
Instead, it had an optimizer of its own that did not take into account
that you can omit sorting by retrieving rows using an index.
Extra optimization has been added: when applicable, single-table
UPDATE/DELETE statements use an existing index instead of filesort. A
corresponding SELECT query would do the former.
Also handling of the DESC ordering expression has been added when
reverse index scan is applicable.
From now on most single table UPDATE and DELETE statements show the
same disk access patterns as the corresponding SELECT query. We verify
this by comparing the result of SHOW STATUS LIKE 'Sort%
Currently the get_index_for_order function
a) checks quick select index (if any) for compatibility with the
ORDER expression list or
b) chooses the cheapest available compatible index, but only if
the index scan is cheaper than filesort.
Second way is implemented by the new test_if_cheaper_ordering
function (extracted part the test_if_skip_sort_order()).
mysql-test/r/log_state.result:
Updated result for optimized query, bug #36569.
mysql-test/r/single_delete_update.result:
Test case for bug #30584, bug #36569 and bug #53742.
mysql-test/r/update.result:
Updated result for optimized query, bug #30584.
Note:
"Handler_read_last 1" omitted, see bug 52312:
lost Handler_read_last status variable.
mysql-test/t/single_delete_update.test:
Test case for bug #30584, bug #36569 and bug #53742.
sql/opt_range.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* get_index_for_order() has been rewritten entirely and moved
to sql_select.cc
New QUICK_RANGE_SELECT::make_reverse method has been added.
sql/opt_range.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* get_index_for_order() has been rewritten entirely and moved
to sql_select.cc
New functions:
* QUICK_SELECT_I::make_reverse()
* SQL_SELECT::set_quick()
sql/records.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* init_read_record_idx() has been modified to allow reverse index scan
New functions:
* rr_index_last()
* rr_index_desc()
sql/records.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
init_read_record_idx() has been modified to allow reverse index scan
sql/sql_delete.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
mysql_delete: an optimization has been added to skip
unnecessary sorting with ORDER BY clause where select
result ordering is acceptable.
sql/sql_select.cc:
Bug #30584, bug #36569, bug #53737, bug #53742:
UPDATE/DELETE ... WHERE ... ORDER BY... always does a filesort
even if not required
The const_expression_in_where function has been modified
to accept both Item and Field pointers.
New functions:
* get_index_for_order()
* test_if_cheaper_ordering() has been extracted from
test_if_skip_sort_order() to share with get_index_for_order()
* simple_remove_const()
sql/sql_select.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* test_if_cheaper_ordering()
* simple_remove_const()
* get_index_for_order()
sql/sql_update.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
mysql_update: an optimization has been added to skip
unnecessary sorting with ORDER BY clause where a select
result ordering is acceptable.
sql/table.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* TABLE::update_const_key_parts()
* is_simple_order()
sql/table.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* TABLE::update_const_key_parts()
* is_simple_order()
2010-06-22 22:32:29 +02:00
|
|
|
#
|
|
|
|
# Single table specific update/delete tests (mysql_update and mysql_delete)
|
|
|
|
#
|
|
|
|
|
2022-06-09 05:32:51 +02:00
|
|
|
# Tests will be skipped for the view protocol because the view protocol creates
|
|
|
|
# an additional util connection and other statistics data
|
|
|
|
-- source include/no_view_protocol.inc
|
|
|
|
|
2023-05-31 06:57:45 +02:00
|
|
|
--disable_ps2_protocol
|
Bug #30584: delete with order by and limit clauses does not
use limit efficiently
Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a
filesort even if not required
Also two bugs reported after QA review (before the commit
of bugs above to public trees, no documentation needed):
Bug #53737: Performance regressions after applying patch
for bug 36569
Bug #53742: UPDATEs have no effect after applying patch
for bug 36569
Execution of single-table UPDATE and DELETE statements did not use the
same optimizer as was used in the compilation of SELECT statements.
Instead, it had an optimizer of its own that did not take into account
that you can omit sorting by retrieving rows using an index.
Extra optimization has been added: when applicable, single-table
UPDATE/DELETE statements use an existing index instead of filesort. A
corresponding SELECT query would do the former.
Also handling of the DESC ordering expression has been added when
reverse index scan is applicable.
From now on most single table UPDATE and DELETE statements show the
same disk access patterns as the corresponding SELECT query. We verify
this by comparing the result of SHOW STATUS LIKE 'Sort%
Currently the get_index_for_order function
a) checks quick select index (if any) for compatibility with the
ORDER expression list or
b) chooses the cheapest available compatible index, but only if
the index scan is cheaper than filesort.
Second way is implemented by the new test_if_cheaper_ordering
function (extracted part the test_if_skip_sort_order()).
mysql-test/r/log_state.result:
Updated result for optimized query, bug #36569.
mysql-test/r/single_delete_update.result:
Test case for bug #30584, bug #36569 and bug #53742.
mysql-test/r/update.result:
Updated result for optimized query, bug #30584.
Note:
"Handler_read_last 1" omitted, see bug 52312:
lost Handler_read_last status variable.
mysql-test/t/single_delete_update.test:
Test case for bug #30584, bug #36569 and bug #53742.
sql/opt_range.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* get_index_for_order() has been rewritten entirely and moved
to sql_select.cc
New QUICK_RANGE_SELECT::make_reverse method has been added.
sql/opt_range.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* get_index_for_order() has been rewritten entirely and moved
to sql_select.cc
New functions:
* QUICK_SELECT_I::make_reverse()
* SQL_SELECT::set_quick()
sql/records.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* init_read_record_idx() has been modified to allow reverse index scan
New functions:
* rr_index_last()
* rr_index_desc()
sql/records.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
init_read_record_idx() has been modified to allow reverse index scan
sql/sql_delete.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
mysql_delete: an optimization has been added to skip
unnecessary sorting with ORDER BY clause where select
result ordering is acceptable.
sql/sql_select.cc:
Bug #30584, bug #36569, bug #53737, bug #53742:
UPDATE/DELETE ... WHERE ... ORDER BY... always does a filesort
even if not required
The const_expression_in_where function has been modified
to accept both Item and Field pointers.
New functions:
* get_index_for_order()
* test_if_cheaper_ordering() has been extracted from
test_if_skip_sort_order() to share with get_index_for_order()
* simple_remove_const()
sql/sql_select.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* test_if_cheaper_ordering()
* simple_remove_const()
* get_index_for_order()
sql/sql_update.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
mysql_update: an optimization has been added to skip
unnecessary sorting with ORDER BY clause where a select
result ordering is acceptable.
sql/table.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* TABLE::update_const_key_parts()
* is_simple_order()
sql/table.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* TABLE::update_const_key_parts()
* is_simple_order()
2010-06-22 22:32:29 +02:00
|
|
|
--echo #
|
|
|
|
--echo # Bug #30584: delete with order by and limit clauses does not use
|
|
|
|
--echo # limit efficiently
|
|
|
|
--echo #
|
|
|
|
|
2024-05-23 03:54:14 +02:00
|
|
|
--disable_cursor_protocol
|
Bug #30584: delete with order by and limit clauses does not
use limit efficiently
Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a
filesort even if not required
Also two bugs reported after QA review (before the commit
of bugs above to public trees, no documentation needed):
Bug #53737: Performance regressions after applying patch
for bug 36569
Bug #53742: UPDATEs have no effect after applying patch
for bug 36569
Execution of single-table UPDATE and DELETE statements did not use the
same optimizer as was used in the compilation of SELECT statements.
Instead, it had an optimizer of its own that did not take into account
that you can omit sorting by retrieving rows using an index.
Extra optimization has been added: when applicable, single-table
UPDATE/DELETE statements use an existing index instead of filesort. A
corresponding SELECT query would do the former.
Also handling of the DESC ordering expression has been added when
reverse index scan is applicable.
From now on most single table UPDATE and DELETE statements show the
same disk access patterns as the corresponding SELECT query. We verify
this by comparing the result of SHOW STATUS LIKE 'Sort%
Currently the get_index_for_order function
a) checks quick select index (if any) for compatibility with the
ORDER expression list or
b) chooses the cheapest available compatible index, but only if
the index scan is cheaper than filesort.
Second way is implemented by the new test_if_cheaper_ordering
function (extracted part the test_if_skip_sort_order()).
mysql-test/r/log_state.result:
Updated result for optimized query, bug #36569.
mysql-test/r/single_delete_update.result:
Test case for bug #30584, bug #36569 and bug #53742.
mysql-test/r/update.result:
Updated result for optimized query, bug #30584.
Note:
"Handler_read_last 1" omitted, see bug 52312:
lost Handler_read_last status variable.
mysql-test/t/single_delete_update.test:
Test case for bug #30584, bug #36569 and bug #53742.
sql/opt_range.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* get_index_for_order() has been rewritten entirely and moved
to sql_select.cc
New QUICK_RANGE_SELECT::make_reverse method has been added.
sql/opt_range.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* get_index_for_order() has been rewritten entirely and moved
to sql_select.cc
New functions:
* QUICK_SELECT_I::make_reverse()
* SQL_SELECT::set_quick()
sql/records.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
* init_read_record_idx() has been modified to allow reverse index scan
New functions:
* rr_index_last()
* rr_index_desc()
sql/records.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
init_read_record_idx() has been modified to allow reverse index scan
sql/sql_delete.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
mysql_delete: an optimization has been added to skip
unnecessary sorting with ORDER BY clause where select
result ordering is acceptable.
sql/sql_select.cc:
Bug #30584, bug #36569, bug #53737, bug #53742:
UPDATE/DELETE ... WHERE ... ORDER BY... always does a filesort
even if not required
The const_expression_in_where function has been modified
to accept both Item and Field pointers.
New functions:
* get_index_for_order()
* test_if_cheaper_ordering() has been extracted from
test_if_skip_sort_order() to share with get_index_for_order()
* simple_remove_const()
sql/sql_select.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* test_if_cheaper_ordering()
* simple_remove_const()
* get_index_for_order()
sql/sql_update.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
mysql_update: an optimization has been added to skip
unnecessary sorting with ORDER BY clause where a select
result ordering is acceptable.
sql/table.cc:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* TABLE::update_const_key_parts()
* is_simple_order()
sql/table.h:
Bug #30584, bug #36569: UPDATE/DELETE ... WHERE ... ORDER BY...
always does a filesort even if not required
New functions:
* TABLE::update_const_key_parts()
* is_simple_order()
2010-06-22 22:32:29 +02:00
|
|
|
CREATE TABLE t1 (i INT);
|
|
|
|
INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
|
|
|
|
(20),(21),(22),(23),(24),(25);
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, i INT PRIMARY KEY);
|
|
|
|
INSERT INTO t2 (i) SELECT i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # index on field prefix:
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, i CHAR(2), INDEX(i(1)));
|
|
|
|
INSERT INTO t2 (i) SELECT i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # constant inside ORDER BY list, should use filesort
|
|
|
|
--echo # on a small table
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c));
|
|
|
|
INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
--echo ## should be 5 (previous LIMIT)
|
|
|
|
eval SELECT $cnt - COUNT(*) FROM t2 WHERE b = 10;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # same test as above (constant inside ORDER BY list), but with
|
|
|
|
--echo # a larger table - should not use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c));
|
|
|
|
INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1;
|
|
|
|
|
|
|
|
INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
--echo ## should be 5 (previous LIMIT)
|
|
|
|
eval SELECT $cnt - COUNT(*) FROM t2 WHERE b = 10;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # as above + partial index, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b(1),c));
|
|
|
|
INSERT INTO t2 SELECT i, i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # as above but index is without HA_READ_ORDER flag, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b,c)) ENGINE=HEAP;
|
|
|
|
INSERT INTO t2 SELECT i, i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # quick select is Index Merge, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (i INT, key1 INT, key2 INT, INDEX (key1), INDEX (key2));
|
|
|
|
INSERT INTO t2 (key1, key2) SELECT i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x
|
|
|
|
EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x
|
|
|
|
EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # reverse quick select, should not use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, i INT PRIMARY KEY);
|
|
|
|
INSERT INTO t2 (i) SELECT i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # mixed sorting direction, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b));
|
|
|
|
INSERT INTO t2 SELECT i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 ORDER BY a, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 ORDER BY a, b DESC;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # LIMIT with no WHERE and DESC direction, should not use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b));
|
|
|
|
INSERT INTO t2 (a, b) SELECT i, i FROM t1;
|
|
|
|
INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 ORDER BY a, b LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
DELETE FROM t2 ORDER BY a DESC, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC;
|
|
|
|
|
|
|
|
DROP TABLE t1, t2;
|
|
|
|
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Bug #36569: UPDATE ... WHERE ... ORDER BY... always does a filesort
|
|
|
|
--echo # even if not required
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t1 (i INT);
|
|
|
|
INSERT INTO t1 VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
|
|
|
|
(20),(21),(22),(23),(24),(25);
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, i INT PRIMARY KEY);
|
|
|
|
INSERT INTO t2 (i) SELECT i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # index on field prefix:
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, i CHAR(2), INDEX(i(1)));
|
|
|
|
INSERT INTO t2 (i) SELECT i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # constant inside ORDER BY list, should use filesort
|
|
|
|
--echo # on a small table
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c));
|
|
|
|
INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
--echo ## should be 5 (previous LIMIT)
|
|
|
|
SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # same test as above (constant inside ORDER BY list), but with
|
|
|
|
--echo # a larger table - should not use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, b INT, c INT, d INT, INDEX(a, b, c));
|
|
|
|
INSERT INTO t2 (a, b, c) SELECT i, i, i FROM t1;
|
|
|
|
|
|
|
|
INSERT INTO t2 (a, b, c) SELECT t1.i, t1.i, t1.i FROM t1, t1 x1, t1 x2;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
let $cnt = `SELECT COUNT(*) FROM t2 WHERE b = 10`;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
--echo ## should be 5 (previous LIMIT)
|
|
|
|
SELECT COUNT(*) FROM t2 WHERE b = 10 AND d = 10 ORDER BY a, c;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # as above + partial index, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b(1),c));
|
|
|
|
INSERT INTO t2 SELECT i, i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # as above but index is without HA_READ_ORDER flag, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), d CHAR(2), INDEX (a,b,c)) ENGINE=HEAP;
|
|
|
|
INSERT INTO t2 SELECT i, i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET d = 10 WHERE b = 10 ORDER BY a, c LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE b = 10 ORDER BY a, c;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # quick select is Index Merge, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (i INT, key1 INT, key2 INT, INDEX (key1), INDEX (key2));
|
|
|
|
INSERT INTO t2 (key1, key2) SELECT i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x
|
|
|
|
EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET i = 123 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x
|
|
|
|
EXPLAIN EXTENDED SELECT * FROM t2 WHERE key1 < 13 or key2 < 14 ORDER BY key1;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # reverse quick select, should not use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2(a INT, i INT PRIMARY KEY);
|
|
|
|
INSERT INTO t2 (i) SELECT i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET a = 10 WHERE i > 10 AND i <= 18 ORDER BY i DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE i > 10 AND i <= 18 ORDER BY i;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # mixed sorting direction, should use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b));
|
|
|
|
INSERT INTO t2 SELECT i, i, i FROM t1;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 ORDER BY a, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET c = 10 ORDER BY a, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE c = 10 ORDER BY a, b DESC;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # LIMIT with no WHERE and DESC direction, should not use filesort
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (a CHAR(2), b CHAR(2), c CHAR(2), INDEX (a, b));
|
|
|
|
INSERT INTO t2 (a, b) SELECT i, i FROM t1;
|
|
|
|
INSERT INTO t2 (a, b) SELECT t1.i, t1.i FROM t1, t1 x1, t1 x2;
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 ORDER BY a, b LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
SELECT * FROM t2 ORDER BY a DESC, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
|
|
|
|
FLUSH STATUS;
|
|
|
|
UPDATE t2 SET c = 10 ORDER BY a DESC, b DESC LIMIT 5;
|
|
|
|
SHOW SESSION STATUS LIKE 'Sort%';
|
|
|
|
SHOW STATUS LIKE 'Handler_read_%';
|
|
|
|
SELECT * FROM t2 WHERE c = 10 ORDER BY a DESC, b DESC;
|
|
|
|
|
|
|
|
DROP TABLE t1, t2;
|
2023-05-31 06:57:45 +02:00
|
|
|
--enable_ps2_protocol
|
2024-05-23 03:54:14 +02:00
|
|
|
--enable_cursor_protocol
|