1. 未满足最左匹配原则
但是如果实现了覆盖索引,就算未满足最左匹配原则也会走索引。
2. select * 有时候会导致索引失效
使用select `查询所有字段 或者未被索引覆盖的字段` 时,如果走索引,还需要进行回表操作,如果回表操作过多,mysql就不会走索引。需要考虑到回表的成本。
3. 索引列上有计算或者使用到函数
4. 字符类型不同(要保持数据类型一致,避免数据类型转换)
1.如果mysql发现int类型作为查询条件时,如果当前字段是字符类的,会对该字段进行隐士转换,转为int类型,(索引会失效)
2.如果mysql发现字符型作为查询条件时,如果当前字段是数字类型的话,会对查询条件进行隐士转换为字符型(索引不会失效)
5. or操作索引失效
or关键字前后字段都需要加上索引,否则会失效。因为如果有一个条件的字段上未建立索引,那么在这个条件查询时会走全表扫描,所以导致索引失效。
- 范围查询特定情况下回引起索引失效
主要是因为,范围查询数据过大,需要进行回表操作,会导致索引失效。
6. order by有时候索引会失效
如果order by能实现覆盖索引,并且覆盖索引的顺序和order by的一致,就不会在进行排序操作。
order by排序有三种:
1. 全字段排序(快速排序)
2. 临时文件辅助排序(归并)
3. row_id排序
mysql会为每个线程分配一小块内存,用于排序使用,sort_buffer 。通过查询到所有数据后,如果还需要排序会将对应的数据放到sort_buffer中。
全字段排序的流程:
1. mysql会为线程初始化sort_buffer,放入需要查询的字段。
2. 如果有可使用的二级索引,则通过二级索引,获取主键id。
3. 通过主键id进行回表(如果,第二步进行了索引覆盖,就可以不用回表)
4. 将获取的数据存入到sort_buffer中。
5. 然后重复执行2,3,4步直到将所有的要排序的数据都放入到sort_buffer中。
6. 在sort_buffer中为数据排序。
7. 将获取的所有结果返回给客户端。(如果有limit则是截取响应的记录结果进行返回)
sort_buffer的大小由sort_buffer_size进行配置,如果要排序的数据小于sort_buffer_size那么 排序在sort_buffer中执行,如果大于sort_buffer_size那么需要进行临时文件辅助排序。
辅助索引排序:当sort_buffer快要满的时候,会对sort_buffer中的数据先进行排序,将排好序的数据放入到一个临时的磁盘文件中。然后在重新向sort_buffer中添加数据,一次类推。直到将所有满足条件的数据取出,然后将磁盘临时排好序的文件进行归并排序。
row_id排序:与全字段排序步骤类似,放入sort_buffer中的数据只包含要排序的字段,等排完续后,在进行回表获取需要返回字段的数据。当要排序的数据单行数据的长度(单行数据的长度为字段所设置的数据类型的大小相加)大于max_length_for_sort_data时,就需要使用row_id排序
order by语句的优化
1. 建立联合索引(对要排序的数据和where里面的参数建立联合索引,建立索引时可以指定每个字段在索引中的排序的方式即正序还是逆序)
2. 进行参数设置,比如max_length_for_sort_data,sort_buffer_size。
3. 有limit时,可以适当的添加一些where条件,来减少要排序数据的数量
7. null值失效(null走不了聚簇索引,因为聚簇索引中不允许有控制)
null ,isnull ,<>这些条件也是可以走索引(非聚簇索引)的,至于是否走索引,是根据其成本来决定的。在mysql真正执行查询语句之前,会先进行预计算,看是否需要走索引,走索引的话非聚簇索引查询成本和回表成本是否大于全表扫描的成本。