--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 #26483909: INCORRECT BEHAVIOR FOR QUERY WITH DISTINCT --echo # and ORDER BY ... LIMIT. --echo # CREATE TABLE t1 ( pk int(11) NOT NULL, col_int int(11), col_varchar_key varchar(20), PRIMARY KEY (pk), KEY col_varchar_key (col_varchar_key), KEY col_varchar_key_2 (col_varchar_key(5)) ); INSERT INTO t1 VALUES (1,2,'t'), (2,5,'efqsdksj'), (3,NULL,'fqsdksjijcs'),(4,8,'qsdksjijc'), (5,40,NULL),(6,3,'sdksji'),(7,2,NULL), (8,3,'dks'),(9,0,'ksjijcsz'), (10,84,'sjijcszxwbjj'); let query1= SELECT DISTINCT col_int FROM t1 WHERE col_varchar_key <> 'c' OR col_varchar_key > 'w' ORDER BY col_varchar_key LIMIT 100; ANALYZE TABLE t1; SET @@SESSION.sql_mode='NO_ENGINE_SUBSTITUTION'; eval EXPLAIN $query1; eval $query1; DROP TABLE t1; --echo # --echo # Bug#29487181 INCORRECT 'ROWS' AND 'FILTERED' ESTIMATE IN --echo # 'ORDER BY ... LIMIT .' QUERIES --echo # CREATE TABLE t1 ( col_int_unique INT DEFAULT NULL, col_int_key INT DEFAULT NULL, UNIQUE KEY col_int_unique (col_int_unique), KEY col_int_key (col_int_key) ); INSERT INTO t1 VALUES (49,49), (9,7), (0,1), (2,42); CREATE TABLE t2 ( col_int_unique INT DEFAULT NULL, pk INT NOT NULL, PRIMARY KEY (pk), UNIQUE KEY col_int_unique (col_int_unique) ); INSERT INTO t2 VALUES (2,8), (5,2), (6,1); ANALYZE TABLE t1,t2; EXPLAIN SELECT STRAIGHT_JOIN t1.col_int_key AS field1 FROM t1 JOIN t2 ON t2.pk = t1.col_int_unique OR t2.col_int_unique = t1.col_int_key ORDER BY field1 LIMIT 2; DROP TABLE t1,t2;