#数据库说明
使用的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';