从具有两个单独索引的 table 中选择不是根据 where 子句中的值使用键
Selecting from a table with two separate indexes is not using a key depending on value in where clause
我正在调整我们的数据库索引并在 Mysql 5.7.32 中发现了一些奇怪的行为。这是复制问题的脚本。
我有一个 table employees
,其中包含三列 id
、firstname
和 lastname
。每个 varchar 列在 table 上有两个索引。对于下面的 SELECT 语句之一,输出意外地没有使用密钥。
为什么其中一个查询没有使用索引?是因为 Miller
是 table 中的第一个值吗?或者这是 EXPLAIN 的错误?
DROP TABLE if EXISTS `employee`;
CREATE TABLE `employee` (
`id` INT(11) NOT NULL auto_increment,
`firstname` VARCHAR(50) NOT NULL,
`lastname` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`),
INDEX `index_firstname` (`firstname`),
INDEX `index_lastname` (`lastname`)
);
INSERT INTO `employee` (firstname,lastname) VALUES('alice','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('bob','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('charlie','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('doyle','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('evan','Smith');
INSERT INTO `employee` (firstname,lastname) VALUES('franz','Smith');
INSERT INTO `employee` (firstname,lastname) VALUES('gloria','Smith');
INSERT INTO `employee` (firstname,lastname) VALUES('helga','Unique');
EXPLAIN SELECT * FROM employee WHERE firstname='alice'; # uses the key 'index_firstname'
EXPLAIN SELECT * FROM employee WHERE lastname='Smith'; # uses the key 'index_lastname'
EXPLAIN SELECT * FROM employee WHERE lastname='Unique'; # uses the key 'index_lastname'
EXPLAIN SELECT * FROM employee WHERE lastname='Miller'; # does not use the key 'index_lastname'
如果索引值的采样占给定值采样的比例超过 ~25%(不准确,请参见下文),则不使用该索引。
有一个成本计算得出扫描完整 table 比使用二级索引更快(需要从主 table 获取以检索 *
) .
我正在调整我们的数据库索引并在 Mysql 5.7.32 中发现了一些奇怪的行为。这是复制问题的脚本。
我有一个 table employees
,其中包含三列 id
、firstname
和 lastname
。每个 varchar 列在 table 上有两个索引。对于下面的 SELECT 语句之一,输出意外地没有使用密钥。
为什么其中一个查询没有使用索引?是因为 Miller
是 table 中的第一个值吗?或者这是 EXPLAIN 的错误?
DROP TABLE if EXISTS `employee`;
CREATE TABLE `employee` (
`id` INT(11) NOT NULL auto_increment,
`firstname` VARCHAR(50) NOT NULL,
`lastname` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`),
INDEX `index_firstname` (`firstname`),
INDEX `index_lastname` (`lastname`)
);
INSERT INTO `employee` (firstname,lastname) VALUES('alice','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('bob','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('charlie','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('doyle','Miller');
INSERT INTO `employee` (firstname,lastname) VALUES('evan','Smith');
INSERT INTO `employee` (firstname,lastname) VALUES('franz','Smith');
INSERT INTO `employee` (firstname,lastname) VALUES('gloria','Smith');
INSERT INTO `employee` (firstname,lastname) VALUES('helga','Unique');
EXPLAIN SELECT * FROM employee WHERE firstname='alice'; # uses the key 'index_firstname'
EXPLAIN SELECT * FROM employee WHERE lastname='Smith'; # uses the key 'index_lastname'
EXPLAIN SELECT * FROM employee WHERE lastname='Unique'; # uses the key 'index_lastname'
EXPLAIN SELECT * FROM employee WHERE lastname='Miller'; # does not use the key 'index_lastname'
如果索引值的采样占给定值采样的比例超过 ~25%(不准确,请参见下文),则不使用该索引。
有一个成本计算得出扫描完整 table 比使用二级索引更快(需要从主 table 获取以检索 *
) .