Description:
Given the following table:
CREATE TABLE `type_test` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`a` double default NULL,
`b` double default NULL,
`c` decimal(10,9) default NULL,
`d` decimal(10,9) default NULL,
PRIMARY KEY (`id`),
KEY `a` (`a`,`b`),
KEY `c` (`c`,`d`)
) ENGINE=InnoDB;
the following queries indicate that the full composite key index will be used:
SELECT * FROM type_test WHERE a BETWEEN 0.001 AND 0.003 AND b BETWEEN 0.005 AND 0.008;
SELECT * FROM type_test WHERE c BETWEEN 0.001 AND 0.003 AND d BETWEEN 0.005 AND 0.008;
SELECT * FROM type_test WHERE a >= 0.001 AND a <= 0.003 AND b >= 0.005 AND b <= 0.008;
SELECT * FROM type_test WHERE c >= 0.001 AND c <= 0.003 AND d >= 0.005 AND d <= 0.008;
and yet the following indicates that only the leading column is used:
SELECT * FROM type_test WHERE a > 0.001 AND a < 0.003 AND b > 0.005 AND b < 0.008;
SELECT * FROM type_test WHERE c > 0.001 AND c < 0.003 AND d > 0.005 AND d < 0.008;
The latter appears to be correct. Checking the handler_read_key and handler_read_next values, all statements increment by exactly the same values (in other words, the actual execution is identical). But the EXPLAIN output indicates that this is not the case:
mysql> EXPLAIN SELECT * FROM type_test WHERE a BETWEEN 0.001 AND 0.003 AND b BETWEEN 0.005 AND 0.008\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: type_test
type: range
possible_keys: a
key: a
key_len: 18
ref: NULL
rows: 105860
Extra: Using where
1 row in set (1.95 sec)
mysql> EXPLAIN SELECT * FROM type_test WHERE c BETWEEN 0.001 AND 0.003 AND d BETWEEN 0.005 AND 0.008\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: type_test
type: range
possible_keys: c
key: c
key_len: 12
ref: NULL
rows: 155718
Extra: Using where
1 row in set (0.09 sec)
mysql>
mysql> EXPLAIN SELECT * FROM type_test WHERE a >= 0.001 AND a <= 0.003 AND b >= 0.005 AND b <= 0.008\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: type_test
type: range
possible_keys: a
key: a
key_len: 18
ref: NULL
rows: 105860
Extra: Using where
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM type_test WHERE c >= 0.001 AND c <= 0.003 AND d >= 0.005 AND d <= 0.008\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: type_test
type: range
possible_keys: c
key: c
key_len: 12
ref: NULL
rows: 155718
Extra: Using where
1 row in set (0.00 sec)
mysql>
mysql> EXPLAIN SELECT * FROM type_test WHERE a > 0.001 AND a < 0.003 AND b > 0.005 AND b < 0.008\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: type_test
type: range
possible_keys: a
key: a
key_len: 9
ref: NULL
rows: 105860
Extra: Using where
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM type_test WHERE c > 0.001 AND c < 0.003 AND d > 0.005 AND d < 0.008\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: type_test
type: range
possible_keys: c
key: c
key_len: 6
ref: NULL
rows: 155718
Extra: Using where
1 row in set (0.00 sec)
It appears that the EXPLAIN output is incorrect when using < and > (instead of <= and >= or BETWEEN).
How to repeat:
DROP TABLE IF EXISTS type_test;
CREATE TABLE type_test (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
a DOUBLE,
b DOUBLE,
c DECIMAL(10,9),
d DECIMAL(10,9),
INDEX (a, b),
INDEX (c, d)
) ENGINE = InnoDB;
INSERT INTO type_test (a, b, c, d) VALUES
(RAND(), RAND(), RAND(), RAND());
INSERT INTO type_test (a, b, c, d)
SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND()
FROM type_test;
INSERT INTO type_test (a, b, c, d)
SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND()
FROM type_test;
EXPLAIN SELECT * FROM type_test WHERE a BETWEEN 0.001 AND 0.003 AND b BETWEEN 0.005 AND 0.008\G
EXPLAIN SELECT * FROM type_test WHERE c BETWEEN 0.001 AND 0.003 AND d BETWEEN 0.005 AND 0.008\G
EXPLAIN SELECT * FROM type_test WHERE a >= 0.001 AND a <= 0.003 AND b >= 0.005 AND b <= 0.008\G
EXPLAIN SELECT * FROM type_test WHERE c >= 0.001 AND c <= 0.003 AND d >= 0.005 AND d <= 0.008\G
EXPLAIN SELECT * FROM type_test WHERE a > 0.001 AND a < 0.003 AND b > 0.005 AND b < 0.008\G
EXPLAIN SELECT * FROM type_test WHERE c > 0.001 AND c < 0.003 AND d > 0.005 AND d < 0.008\G
Description: Given the following table: CREATE TABLE `type_test` ( `id` bigint(20) unsigned NOT NULL auto_increment, `a` double default NULL, `b` double default NULL, `c` decimal(10,9) default NULL, `d` decimal(10,9) default NULL, PRIMARY KEY (`id`), KEY `a` (`a`,`b`), KEY `c` (`c`,`d`) ) ENGINE=InnoDB; the following queries indicate that the full composite key index will be used: SELECT * FROM type_test WHERE a BETWEEN 0.001 AND 0.003 AND b BETWEEN 0.005 AND 0.008; SELECT * FROM type_test WHERE c BETWEEN 0.001 AND 0.003 AND d BETWEEN 0.005 AND 0.008; SELECT * FROM type_test WHERE a >= 0.001 AND a <= 0.003 AND b >= 0.005 AND b <= 0.008; SELECT * FROM type_test WHERE c >= 0.001 AND c <= 0.003 AND d >= 0.005 AND d <= 0.008; and yet the following indicates that only the leading column is used: SELECT * FROM type_test WHERE a > 0.001 AND a < 0.003 AND b > 0.005 AND b < 0.008; SELECT * FROM type_test WHERE c > 0.001 AND c < 0.003 AND d > 0.005 AND d < 0.008; The latter appears to be correct. Checking the handler_read_key and handler_read_next values, all statements increment by exactly the same values (in other words, the actual execution is identical). But the EXPLAIN output indicates that this is not the case: mysql> EXPLAIN SELECT * FROM type_test WHERE a BETWEEN 0.001 AND 0.003 AND b BETWEEN 0.005 AND 0.008\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: type_test type: range possible_keys: a key: a key_len: 18 ref: NULL rows: 105860 Extra: Using where 1 row in set (1.95 sec) mysql> EXPLAIN SELECT * FROM type_test WHERE c BETWEEN 0.001 AND 0.003 AND d BETWEEN 0.005 AND 0.008\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: type_test type: range possible_keys: c key: c key_len: 12 ref: NULL rows: 155718 Extra: Using where 1 row in set (0.09 sec) mysql> mysql> EXPLAIN SELECT * FROM type_test WHERE a >= 0.001 AND a <= 0.003 AND b >= 0.005 AND b <= 0.008\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: type_test type: range possible_keys: a key: a key_len: 18 ref: NULL rows: 105860 Extra: Using where 1 row in set (0.00 sec) mysql> EXPLAIN SELECT * FROM type_test WHERE c >= 0.001 AND c <= 0.003 AND d >= 0.005 AND d <= 0.008\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: type_test type: range possible_keys: c key: c key_len: 12 ref: NULL rows: 155718 Extra: Using where 1 row in set (0.00 sec) mysql> mysql> EXPLAIN SELECT * FROM type_test WHERE a > 0.001 AND a < 0.003 AND b > 0.005 AND b < 0.008\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: type_test type: range possible_keys: a key: a key_len: 9 ref: NULL rows: 105860 Extra: Using where 1 row in set (0.00 sec) mysql> EXPLAIN SELECT * FROM type_test WHERE c > 0.001 AND c < 0.003 AND d > 0.005 AND d < 0.008\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: type_test type: range possible_keys: c key: c key_len: 6 ref: NULL rows: 155718 Extra: Using where 1 row in set (0.00 sec) It appears that the EXPLAIN output is incorrect when using < and > (instead of <= and >= or BETWEEN). How to repeat: DROP TABLE IF EXISTS type_test; CREATE TABLE type_test ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, a DOUBLE, b DOUBLE, c DECIMAL(10,9), d DECIMAL(10,9), INDEX (a, b), INDEX (c, d) ) ENGINE = InnoDB; INSERT INTO type_test (a, b, c, d) VALUES (RAND(), RAND(), RAND(), RAND()); INSERT INTO type_test (a, b, c, d) SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a / RAND(), b / RAND(), c / RAND(), d / RAND() FROM type_test; INSERT INTO type_test (a, b, c, d) SELECT a * RAND(), b * RAND(), c * RAND(), d * RAND() FROM type_test; EXPLAIN SELECT * FROM type_test WHERE a BETWEEN 0.001 AND 0.003 AND b BETWEEN 0.005 AND 0.008\G EXPLAIN SELECT * FROM type_test WHERE c BETWEEN 0.001 AND 0.003 AND d BETWEEN 0.005 AND 0.008\G EXPLAIN SELECT * FROM type_test WHERE a >= 0.001 AND a <= 0.003 AND b >= 0.005 AND b <= 0.008\G EXPLAIN SELECT * FROM type_test WHERE c >= 0.001 AND c <= 0.003 AND d >= 0.005 AND d <= 0.008\G EXPLAIN SELECT * FROM type_test WHERE a > 0.001 AND a < 0.003 AND b > 0.005 AND b < 0.008\G EXPLAIN SELECT * FROM type_test WHERE c > 0.001 AND c < 0.003 AND d > 0.005 AND d < 0.008\G