MySQL复合索引中七种常见的索引失效情形

#数据库说明
使用的table emp如下:

CREATE TABLE emp(
	id INT(11) NOT NULL AUTO_INCREMENT,
	empno INT NOT NULL,
	NAME VARCHAR(20) DEFAULT NULL,
	age INT(3) DEFAULT NULL,
	deptid INT(11) DEFAULT NULL,
	PRIMARY KEY (id)
)
ENGINE = INNODB AUTO_INCREMENT=1 DEFAULT CHARSET =utf8;

然后在其中随机插入500000条数据

尝试建立age_name_deptid顺序的复合索引,并查询执行情况

CREATE INDEX idx_age_name_deptid ON emp(age, NAME, deptid);

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.`age`=30
AND emp.name='abcd'
AND emp.`deptid`=4;

结果如下:
在这里插入图片描述
以上为索引正常使用情况,可以看到在使用索引后,物理行由500000减少到1,提高了效率。下面以此为基础介绍七种索引失效情形

**


1. 情形1 第一个位置缺少查询项


**

CREATE INDEX idx_age_name_deptid ON emp(age, NAME, deptid);

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE  emp.name='abcd' AND emp.`deptid`=4;

结果如下:
查询结果
物理行rows接近500000,可见查询结果为全表查询


2. 情形2 索引中断,则中断后面部分的索引无效

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.`deptid`=4;

结果如下:
在这里插入图片描述
可见,虽然查询的物理行下降到4万多,但比全表扫描效率高,但比最佳情况要差。这是因为已建立的索引顺序为age_name_deptid,而这个查询为age_deptid,在name处中断了,中断后的索引失效。

3. 情形3 在索引列上使用函数

CREATE INDEX idx_name ON emp(NAME);

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.`name` LIKE 'abc%';
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE LEFT(emp.`name`,3) = 'abc';

第一条查询结果

第二条查询结果
在这里插入图片描述

4. 情形4 存储引擎不能使用索引中范围条件右边的列**

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.`deptid`=4 AND emp.name='abcd';
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE emp.age=30 AND emp.`deptid`>=4 AND emp.name='abcd';

5. 情形5 出现不等于时不能使用索引

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE  emp.`deptid`=4;

CREATE INDEX idx_deptid ON emp(deptid);

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE  emp.`deptid`=4;
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE  emp.`deptid`<>4;

结果如下:
在这里插入图片描述

*6. 情形6 is not null无法使用索引,但is null可以使用索引

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE age IS NULL;
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE age IS NOT NULL;

7. 情形7 like‘%xxx’时索引失效*

EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE NAME LIKE 'abc';
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE NAME LIKE 'abc%';
EXPLAIN SELECT SQL_NO_CACHE * FROM emp WHERE NAME LIKE '%abc';

猜你喜欢

转载自blog.csdn.net/vivian233/article/details/109801868