索引使用原则
1.选择合适的字段创建索引:
- 不为 NULL 的字段 :索引字段的数据应该尽量不为 NULL,因为对于数据为 NULL 的字段,数据库较难优化。如果字段频繁被查询,但又避免不了为 NULL,建议使用 0,1,true,false 这样语义较为清晰的短值或短字符作为替代。
- 被频繁查询或可用以缩小查询范围的字段上建立索引的字段 :对于查询中使用很少或者重复值比较多的列(因为索引的重复值越低,选择性越强),不宜建立索引。
- 频繁需要 group by 或 order by 的字段 :索引已经排序,这样查询可以利用索引的排序,加快排序查询时间。对于 group by 后又 order by 的情况,如果两个字段建立了联合索引,查询的效果可能会比单个效果好的多。
- 被经常频繁用于连接的字段 :经常用于连接的字段可能是一些外键列,对于外键列并不一定要建立外键,只是说该列涉及到表与表的关系。对于频繁被连接查询的字段,可以考虑建立索引,提高多表连接查询的效率。
- 经常需要 distinct 的字段:由于 distinct 的步骤就是先排序,再去重。如果已经排好序了,那不就帮大忙了?
2.被频繁更新的字段应该慎重建立索引。
虽然索引能带来查询上的效率,但是维护索引的成本也是不小的。 如果一个字段不被经常查询,反而被经常修改,那么就更不应该在这种字段上建立索引了。
3.尽可能的考虑建立联合索引而不是单列索引。
因为索引是需要占用磁盘空间的,可以简单理解为每个索引都对应着一颗 B+树。如果一个表的字段过多,索引过多,那么当这个表的数据达到一个体量后,索引占用的空间也是很多的,且修改索引时,耗费的时间也是较多的。如果是联合索引,多个字段在一个索引上,那么将会节约很大磁盘空间,且修改数据的操作效率也会提升。
此外,使用多列索引时,选择性强(字段的重复值越低,选择性越强)的放左边。
4.注意避免冗余索引
冗余索引指的是索引的功能相同,能够命中索引(a, b)就肯定能命中索引(a) ,那么索引(a)就是冗余索引。如(name,city )和(name )这两个索引就是冗余索引,能够命中前者的查询肯定是能够命中后者的。在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。
5.考虑在字符串类型的字段上使用前缀索引代替普通索引。
前缀索引仅限于字符串类型,较普通索引会占用更小的空间,所以可以考虑使用前缀索引带替普通索引。不过坏处就是不能排序的时候用不到索引了,只能走文件排序的逻辑。
6.避免一些导致索引失效的情况。
7.在使用 InnoDB 时使用与业务无关的自增主键作为主键,即使用逻辑主键,而不要使用业务主键。
8.选取字节空间占用小的列创建索引,尤其是作为主键的时候:因为创建索引时需要把索引列维护到索引树中,尤其是主键值,不管是主键索引还是二级索引中都会用到,如果主键本身占用磁盘空间较大,那索引占据的整体磁盘空间就会比较大了。
9.不建议用无序的值作为索引:例如 UUID(在索引比较时需要转为ASCII,并且插入时可能造成页分裂)、MD5、HASH、无序长字符串等。
索引失效的几种场景
一:不符合最左前缀匹配原则:
- like 以 % 开头
- 使用联合索引时,没用到最左边的字段
二:隐式转换:
- 列字段是字符串类型,但没有将过滤条件用引号括起来,比如用的是数值类型。此时 MySQL 会对列进行函数操作,将其转成数值类型,再进行比较。导致索引失效。反之,如果字段是数值类型,但条件写成了字符串,则不会有索引失效的问题。因为此时的隐式转换是作用于条件上的。
- 索引字段是表达式的一部分,或者是函数的参
三:使用 != 或 <> 的时候:使用 “=” 的时候可以用二分法在索引树中检索,但不等于就无法确定搜索路径了。同理 is not null、not like 也走不了索引。(is null 可以)。