From 45cad70ff4b9e191e9ac553298e25fe500a747c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 9 Oct 2006 19:51:41 +0400 Subject: [PATCH] Bug #22781: SQL_BIG_RESULT fails to influence sort plan Currently SQL_BIG_RESULT is checked only at compile time. However, additional optimizations may take place after this check that change the sort method from 'filesort' to sorting via index. As a result the actual plan executed is not the one specified by the SQL_BIG_RESULT hint. Similarly, there is no such test when executing EXPLAIN, resulting in incorrect output. The patch corrects the problem by testing for SQL_BIG_RESULT both during the explain and execution phases. mysql-test/r/bdb.result: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - updated sql_big_result testcase mysql-test/r/group_by.result: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - test case with MyISAM mysql-test/r/innodb.result: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - updated sql_big_result testcase mysql-test/r/innodb_mysql.result: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - test case with InnoDB mysql-test/r/myisam.result: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - updated sql_big_result testcase mysql-test/t/group_by.test: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - test case with MyISAM mysql-test/t/innodb_mysql.test: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - test case with InnoDB sql/sql_select.cc: Bug #22781: SQL_BIG_RESULT fails to influence sort plan - When SQL_BIG_RESULT is specified, disable the optimization performed at execution/explain time that decides to use an index instead of filesort. --- mysql-test/r/bdb.result | 72 ++++++++++++++++---------------- mysql-test/r/group_by.result | 67 ++++++++++++++++++++++++++++- mysql-test/r/innodb.result | 16 +++---- mysql-test/r/innodb_mysql.result | 16 +++++++ mysql-test/r/myisam.result | 16 +++---- mysql-test/t/group_by.test | 22 ++++++++++ mysql-test/t/innodb_mysql.test | 18 ++++++++ sql/sql_select.cc | 13 ++++-- 8 files changed, 183 insertions(+), 57 deletions(-) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index ee7cdceefda..c5b3b1f86e7 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1509,27 +1509,27 @@ i 10 select sql_big_result v,count(t) from t1 group by v limit 10; v count(t) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 +h 10 +i 10 select sql_big_result v,count(c) from t1 group by v limit 10; v count(c) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 +h 10 +i 10 select c,count(*) from t1 group by c limit 10; c count(*) a 1 @@ -1673,15 +1673,15 @@ i 10 select sql_big_result v,count(t) from t1 group by v limit 10; v count(t) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 +h 10 +i 10 alter table t1 drop key v, add key v (v(30)); show create table t1; Table Create Table @@ -1800,15 +1800,15 @@ i 10 select sql_big_result v,count(t) from t1 group by v limit 10; v count(t) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 -h 10 -i 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 +h 10 +i 10 drop table t1; create table t1 (a char(10), unique (a)); insert into t1 values ('a '); diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 5eb2e5744c1..5a55abbc923 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -303,10 +303,10 @@ spid sum(userid) 1 1 explain select sql_big_result score,count(*) from t1 group by score desc; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL score 3 NULL 8 Using index +1 SIMPLE t1 index NULL score 3 NULL 8 Using index; Using filesort explain select sql_big_result score,count(*) from t1 group by score desc order by null; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL score 3 NULL 8 Using index +1 SIMPLE t1 index NULL score 3 NULL 8 Using index; Using filesort select sql_big_result score,count(*) from t1 group by score desc; score count(*) 3 5 @@ -821,3 +821,66 @@ a b real_b 68 France France DROP VIEW v1; DROP TABLE t1,t2; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, key (b)); +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20) FROM t1; +INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20) FROM t1; +INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20) FROM t1; +INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20) FROM t1; +INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20) FROM t1; +INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20) FROM t1; +INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20) FROM t1; +SELECT MIN(b), MAX(b) from t1; +MIN(b) MAX(b) +0 19 +EXPLAIN SELECT b, sum(1) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL b 5 NULL 128 Using index +EXPLAIN SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL b 5 NULL 128 Using index; Using filesort +SELECT b, sum(1) FROM t1 GROUP BY b; +b sum(1) +0 6 +1 7 +2 7 +3 7 +4 7 +5 7 +6 7 +7 7 +8 7 +9 6 +10 6 +11 6 +12 6 +13 6 +14 6 +15 6 +16 6 +17 6 +18 6 +19 6 +SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b; +b sum(1) +0 6 +1 7 +2 7 +3 7 +4 7 +5 7 +6 7 +7 7 +8 7 +9 6 +10 6 +11 6 +12 6 +13 6 +14 6 +15 6 +16 6 +17 6 +18 6 +19 6 +DROP TABLE t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 1d1f26e4b01..38d71ac7a42 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2070,15 +2070,15 @@ i 10 select sql_big_result v,count(c) from t1 group by v limit 10; v count(c) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 h 10 -i 10 +i 10 select c,count(*) from t1 group by c limit 10; c count(*) a 1 diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index b4101e037f2..c4564251a35 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -337,3 +337,19 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 index NULL fkey 5 NULL 5 Using index 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.fkey 1 Using where DROP TABLE t1,t2; +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB; +INSERT INTO t1 VALUES ( 1 , 1 , 1); +INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20), 1 FROM t1; +EXPLAIN SELECT b, SUM(c) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL b 5 NULL 128 +EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 128 Using filesort +DROP TABLE t1; diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 0021e6717ee..b1d5765a304 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1002,15 +1002,15 @@ i 10 select sql_big_result v,count(c) from t1 group by v limit 10; v count(c) a 1 -a 10 -b 10 -c 10 -d 10 -e 10 -f 10 -g 10 +a 10 +b 10 +c 10 +d 10 +e 10 +f 10 +g 10 h 10 -i 10 +i 10 select c,count(*) from t1 group by c limit 10; c count(*) a 1 diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index ce1e4e59600..5d47f64f3d1 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -655,3 +655,25 @@ where t2.b=v1.a GROUP BY t2.b; DROP VIEW v1; DROP TABLE t1,t2; + +# +# Bug#22781: SQL_BIG_RESULT fails to influence sort plan +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, key (b)); + +INSERT INTO t1 VALUES (1, 1); +INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20) FROM t1; +INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20) FROM t1; +INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20) FROM t1; +INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20) FROM t1; +INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20) FROM t1; +INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20) FROM t1; +INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20) FROM t1; + +SELECT MIN(b), MAX(b) from t1; + +EXPLAIN SELECT b, sum(1) FROM t1 GROUP BY b; +EXPLAIN SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b; +SELECT b, sum(1) FROM t1 GROUP BY b; +SELECT SQL_BIG_RESULT b, sum(1) FROM t1 GROUP BY b; +DROP TABLE t1; diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 59dbe5e96d4..4d87e9dfb02 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -302,3 +302,21 @@ SELECT COUNT(*) FROM t2 LEFT JOIN t1 ON t2.fkey = t1.id WHERE t1.name LIKE 'A%' OR FALSE; DROP TABLE t1,t2; + +# +# Bug#22781: SQL_BIG_RESULT fails to influence sort plan +# +CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c FLOAT, KEY b(b)) ENGINE = INNODB; + +INSERT INTO t1 VALUES ( 1 , 1 , 1); +INSERT INTO t1 SELECT a + 1 , MOD(a + 1 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 2 , MOD(a + 2 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 4 , MOD(a + 4 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 8 , MOD(a + 8 , 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 16, MOD(a + 16, 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 32, MOD(a + 32, 20), 1 FROM t1; +INSERT INTO t1 SELECT a + 64, MOD(a + 64, 20), 1 FROM t1; + +EXPLAIN SELECT b, SUM(c) FROM t1 GROUP BY b; +EXPLAIN SELECT SQL_BIG_RESULT b, SUM(c) FROM t1 GROUP BY b; +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b328d9162d5..e9c282c1d24 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1399,7 +1399,8 @@ JOIN::exec() simple_order= simple_group; skip_sort_order= 0; } - if (order && + if (order && + (order != group_list || !(select_options & SELECT_BIG_RESULT)) && (const_tables == tables || ((simple_order || skip_sort_order) && test_if_skip_sort_order(&join_tab[const_tables], order, @@ -11995,11 +11996,17 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, table= tab->table; select= tab->select; - if (test_if_skip_sort_order(tab,order,select_limit,0)) + /* + When there is SQL_BIG_RESULT do not sort using index for GROUP BY, + and thus force sorting on disk. + */ + if ((order != join->group_list || + !(join->select_options & SELECT_BIG_RESULT)) && + test_if_skip_sort_order(tab,order,select_limit,0)) DBUG_RETURN(0); if (!(sortorder=make_unireg_sortorder(order,&length))) goto err; /* purecov: inspected */ - /* It's not fatal if the following alloc fails */ + table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE), MYF(MY_WME | MY_ZEROFILL)); table->status=0; // May be wrong if quick_select