Current Path : /home/usr.opt/mysql57/mysql-test/t/ |
FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64 |
Current File : //home/usr.opt/mysql57/mysql-test/t/order_by_limit.test |
--echo # --echo # WL#6986 : Make switching of index due to order by limit cost based --echo # --echo # Testcase for Bug#16522053 CREATE TABLE t1 ( pk INT PRIMARY KEY AUTO_INCREMENT, i INT, j INT, INDEX (i), INDEX (j) ); INSERT INTO t1 (i,j) VALUES (1,1); let $1=7; set @d=1; while ($1) { eval INSERT INTO t1 (i,j) SELECT i+@d, j+@d from t1; eval set @d=@d*2; dec $1; } ANALYZE TABLE t1; let $query= SELECT * FROM t1 WHERE i<100 AND j<10 ORDER BY i LIMIT 5; eval EXPLAIN $query; eval $query; DROP TABLE t1; CREATE TABLE t0 ( i0 INTEGER NOT NULL ); INSERT INTO t0 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); CREATE TABLE t1 ( pk INTEGER PRIMARY KEY, i1 INTEGER NOT NULL, i2 INTEGER NOT NULL, INDEX k1 (i1), INDEX k2 (i1,i2) ) ENGINE=InnoDB; INSERT INTO t1 SELECT a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0, (a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0) % 1000, (a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0) % 1000 FROM t0 AS a0, t0 AS a1; CREATE TABLE t2 ( pk INTEGER PRIMARY KEY, i1 INTEGER NOT NULL, INDEX k1 (i1) ) ENGINE=InnoDB; INSERT INTO t2 SELECT a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0, (a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0) % 500 FROM t0 AS a0, t0 AS a1; ANALYZE TABLE t1,t2; --echo # Query should use index to optimize the ORDER BY LIMIT let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 and t1.i1 > 2 ORDER BY t1.i1 LIMIT 2; eval EXPLAIN $query; --echo # Query should not make the switch to use index to --echo # optimize ORDER BY LIMIT. So should be using filesort let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 and t1.i1 > 2 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; --echo # Changing range condition on i1 should make --echo # key on i1 get picked to give the order let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 and t1.i1 > 800 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; --echo # Use range condition only on pk to see if switch --echo # happens just for ORDER BY LIMIT --echo # Should not happen unless range results in too --echo # many records let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 1000 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; --echo # check if switch happens when the index for order --echo # by is non-covering let query= SELECT t1.i1,t1.i2 FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 100 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; --echo # Reduce the fanout for table t2 and check --echo # that index for order by is not choosen let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 and t2.pk = 100 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; --echo # Increase the fanout to see if index gets choosen --echo # for order by for which range scan was choosen --echo # earlier INSERT INTO t2 SELECT a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0 + 1, (a0.i0 + 10*a1.i0 + 100*a0.i0 + 1000*a1.i0) % 500 FROM t0 AS a0, t0 AS a1; ANALYZE TABLE t2; let query= SELECT * FROM t1 STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; --echo # Check if the index for order by is used when --echo # force index is done on order by let query= SELECT * FROM t1 FORCE INDEX FOR ORDER BY (k2) STRAIGHT_JOIN t2 ON t1.i1=t2.i1 WHERE t1.pk > 7000 ORDER BY t1.i1 LIMIT 5; eval EXPLAIN $query; eval $query; DROP TABLE t0, t1, t2; --echo # --echo # Bug 31686878 - BACKPORT MAIN BUG 30348211 TO RELEASE 5.7 --echo # CREATE TABLE t (id BIGINT NOT NULL, other_id BIGINT NOT NULL, covered_column VARCHAR(50) NOT NULL, non_covered_column VARCHAR(50) NOT NULL, PRIMARY KEY (id), INDEX index_other_id_covered_column (other_id, covered_column)); let $n = 10; while ($n) { eval INSERT INTO t (id, other_id, covered_column, non_covered_column) VALUES ($n, $n, '$n', '$n'); dec $n; } SET optimizer_trace = "enabled=on", optimizer_trace_max_mem_size = 1000000, end_markers_in_json = ON; #echo "With prefer_ordering_index=on, ordering index will be picked." #echo "The original plan is discarded and a new one using ordering index " #echo "is picked." SET optimizer_switch = "prefer_ordering_index=on"; ANALYZE TABLE t; EXPLAIN SELECT non_covered_column FROM t WHERE other_id > 3 ORDER BY id ASC LIMIT 2; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; #echo "With prefer_ordering_index=off, ordering index should not be picked" SET optimizer_switch = "prefer_ordering_index=off"; EXPLAIN SELECT non_covered_column FROM t WHERE other_id > 3 ORDER BY id ASC LIMIT 2; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_0 FROM information_schema.optimizer_trace; #echo "With prefer_ordering_index=default, ordering index should be picked" SET optimizer_switch = default; EXPLAIN SELECT non_covered_column FROM t WHERE other_id > 3 ORDER BY id ASC LIMIT 2; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; #echo "If an order by index is forced, plan will be to pick ordering index even if" #echo "prefer_ordering_index is switched off" SET optimizer_switch = "prefer_ordering_index=on"; EXPLAIN SELECT non_covered_column FROM t FORCE INDEX(PRIMARY) WHERE other_id > 3 ORDER BY id ASC LIMIT 2; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; SET optimizer_switch = "prefer_ordering_index=off"; EXPLAIN SELECT non_covered_column FROM t FORCE INDEX(PRIMARY) WHERE other_id > 3 ORDER BY id ASC LIMIT 2; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; #Insert some more data for group by let $n = 10; while ($n) { eval INSERT INTO t (id, other_id, covered_column, non_covered_column) VALUES ($n+1+10, $n, '$n', '$n'); dec $n; } --source include/turn_off_only_full_group_by.inc #echo "With prefer_ordering_index=on, ordering index will be picked." #echo "The original plan is discarded and a new one using ordering index " #echo "is picked." SET optimizer_switch = "prefer_ordering_index=on"; ANALYZE TABLE t; EXPLAIN SELECT non_covered_column FROM t WHERE id > 8 GROUP BY other_id LIMIT 1; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; #echo "With prefer_ordering_index=off, ordering index should not be picked" SET optimizer_switch = "prefer_ordering_index=off"; #EXPLAIN SELECT non_covered_column FROM t WHERE id > 8 GROUP BY other_id LIMIT 1; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_0 FROM information_schema.optimizer_trace; #echo "With prefer_ordering_index=default, ordering index should be picked" SET optimizer_switch = default; EXPLAIN SELECT non_covered_column FROM t WHERE id > 8 GROUP BY other_id LIMIT 1; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; #echo "If a group by index is forced, plan will be to pick ordering index " #echo "even if prefer_ordering_index is switched off" SET optimizer_switch = "prefer_ordering_index=on"; EXPLAIN SELECT non_covered_column FROM t FORCE INDEX FOR GROUP BY (index_other_id_covered_column) WHERE id > 8 GROUP BY other_id LIMIT 1; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; SET optimizer_switch = "prefer_ordering_index=off"; EXPLAIN SELECT non_covered_column FROM t FORCE INDEX FOR GROUP BY (index_other_id_covered_column) WHERE id > 8 GROUP BY other_id LIMIT 1; SELECT (trace LIKE '%"plan_changed": true%') AS should_be_1 FROM information_schema.optimizer_trace; --source include/restore_sql_mode_after_turn_off_only_full_group_by.inc DROP TABLE t;