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