EXPLAIN SELECT * FROM staff WHERE s_no !=1 AND s_no != 2;
EXPLAIN SELECT * FROM staff WHERE s_no NOT IN (1,2);
使用IN优化,命中索引:
EXPLAIN SELECT * FROM staff WHERE s_no IN (11,12);
但是使用 IN 命中索引有个前提,是查询条件字段数据区分度要高,通常如:状态、类型、性别之类的字段。
** 12、排序对索引的影响**
ORDER BY是经常用的语句,排序也遵循最左前缀列的原则。
查询所有列未命中索引:
EXPLAIN SELECT * FROM staff ORDER BY name,work_age;
覆盖索引查询可命中索引:
覆盖索引能够利用联合索引查询,但是 ORDER BY 后的条件查询不符合最左前缀原则,执行结果 Extra 中出现了 Using filesort 的提示,一般看到这个就要想办法优化了。
调整排序的两个字段顺序之后,Extra 会提示为 Using index,使用了索引,避免了排序的资源开销:
EXPLAIN SELECT name,work_age FROM staff ORDER BY name,work_age;
** 13、局部索引的使用**
局部索引,区别于最左列索引(顺序取索引中靠左的列的查询),它只取某列的一部分作为索引。
INNODB存储引擎下,一般是字符串类型,很长,全部作为索引大大增加存储空间,索引也需要维护,对于长字符串,又想作为索引列,可取的办法就是取前一部分(局部),代表一整列作为索引串。
如何确保这个前缀能代表或大致代表这一列?MySQL中有个概念是 索引选择性,是指索引中不重复的值的数目(也称基数X)与整个表该列记录总数(T)的比值。基数可以通过SHOW INDEX FROM 表名 查看。
比如一个列表 [1,2,2,3,5,6],总数是 6,不重复值数目为 5,选择性为 5/6,因此选择性范围是[X/T, 1],这个值越大,表示列中不重复值越多,越适合作为局部索引,而唯一索引(UNIQUE KEY)的选择性是1。
`SELECT COUNT(DISTINCT(CONCAT(LEFT(remark, N))/COUNT(*) FROM t; 测试出接近 1 的索引选择性,其中N是索引的长度,穷举法去找出N的值,然后再建索引。
创建 局部索引 ,使用 remark 字段举个例子
EXPLAIN SELECT * FROM staff where remark LIKE 'xxx%';
对 remark 字段重建局部索引:
ALTER TABLE staff DROP INDEX idx_remark_part, ADD INDEX idx_remark_part(remark(5));再次执行查询:
EXPLAIN SELECT * FROM staff where remark LIKE 'xxx%';
索引优化总结上面列了大部分场景索引最佳实战,除此之外,不宜建索引的几点小总结:
1)更新非常频繁字段不宜建索引
因为字段更新台频繁,会导致B+树的频繁的变更,重建索引。所以这个过程是十分消耗数据库性能的。
2)区分度不大的字段不宜建索引
比如类似性别这类的字段,区分度不大,建立索引的意义不大。因为不能有效过滤数据,性能和全表扫描相当。另外注意一点,返回数据的比例在 30% 之外的,优化器不会选择使用索引。
3)业务中有唯一特性的字段,建议建成唯一索引