我试图弄清索引中mySQL中的设置。 MySQL什么时候忽略索引?
这是实验的结果。我有一个表,在AGE列上有一个索引,如下所示。
CREATE TABLE `USERS` (
`ID` int(11) NOT NULL,
`FIRSTNAME` varchar(45) NOT NULL,
`LASTNAME` varchar(45) DEFAULT NULL,
`USERNAME` varchar(45) DEFAULT NULL,
`ROLE` int(11) DEFAULT NULL,
`PASSWORD` varchar(45) DEFAULT NULL,
`AGE` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `USERS`
ADD PRIMARY KEY (`ID`),
ADD KEY `AGE` (`AGE`);
EXPLAIN查询的结果。前三个语句使用索引。第二组语句忽略索引并进行全表扫描。
年龄范围在20至100年之间是随机的。表中有1000行。
/* utilizes the index on AGE */
/* case 1 */
SELECT ID, AGE FROM USERS WHERE AGE > 20;
/* case 2 */
SELECT AGE FROM USERS WHERE AGE > 44;
/* case 3 */
SELECT * FROM USERS WHERE AGE > 84;
/* does not use index on AGE */
/* case 4 */
SELECT AGE, FIRSTNAME FROM USERS WHERE AGE > 83;
/* case 5 */
SELECT * FROM USERS WHERE AGE > 83;
/* case 6 */
SELECT AGE FROM USERS WHERE AGE > 18;
我看到的一些观察结果。谁能证实我的结论是正确的?
1)SELECT *将在选择15%或更少的行时使用索引。 2)选择1行或更多行时,SELECT AGE将使用索引。
答案 0 :(得分:2)
15%通常约为20%,这取决于从表中数据收集的统计信息。我看到有人在查询中设定了约29%的临界值。您实际上达到了20%:
(100-85+1)/(100-20+1) = 19.8%
(100-84+1)/(100-20+1) = 21.0%
因此,这可以解释情况3、4、5。其理由是,对于较高的百分比,表扫描比在索引BTree和数据+ PK BTree之间跳动更为有效。
这两个索引正在“覆盖”。也就是说,所有必要的列都在单个索引中找到。因此,它应该使用索引,而不是进行表扫描:
SELECT AGE ...
SELECT ID, AGE ...
注意:在InnoDB中,辅助索引隐式包含PRIMARY KEY
。也就是说,INDEX(age)
实际上与INDEX(age, id)
相同。
这说明了情况1和2,但没有解释情况6。情况6应该使用索引返回AGE的整个列表。 (不是0行,如您的注释所述?)
您的测试只是冰山一角,但是您比大多数初学者都更加了解MySQL相对简单的Optimizer的深度。 (我已经好几年开始了。)
还有更多经验法则here。
请继续尝试并发布您的结果。