1. 全值匹配索引
如有索引 index_id 对应索引字段为 id,和索引index_id_name对应索引字段为id 和 name,这时条件中使用了id和name,如 where id=1 and name=‘zs’ 时, 索引 index_id 失效。即条件中有多个字段时,优先考虑匹配条件中的组合索引。
2. 最左匹配原则
MySQL中最多可建立16个索引,当使用组合索引时,需要注意索引匹配是从最左的索引字段开始,若跳过某一个字段,后面的索引字段全失效。 如一张表仅有一个索引且为组合索引,字段排序为 id,name,age,address
序号 | 条件 | 是否使用到该索引 | 索引匹配的字段 |
---|
1 | where id = 1 | 是 | id | 2 | where id = 1 and age= 26 | 是 | id,age | 3 | where id = 1 and age= 26 and name = ‘zs’ | 是 | id,name, age | 4 | where id = 1 and age= 26 | 是 | id | 5 | where id = 1 and age= 26 and name = ‘zs’ and address = ‘sh’ | 是 | id,name,age,address | 6 | where id = 1 and name = ‘zs’ and address = ‘sh’ | 是 | id,name | 7 | where age= 26 | 否 | | 8 | where name = ‘zs’ and address = ‘sh’ | 否 | |
注意1,2,3,5 的条件的索引条件字段都匹配了,因为条件语句中出现的条件字段在符合组合索引中从左到右。 再看4,6的条件也用上了索引,但 4 中的字段age没有匹配上,因为age字段左边的name字段没有导致age字段被跳过,同样在 6 中address也因为左边字段age没有导致被跳过。 在7,8的条件中,最左边的字段id不存在,因此后面字段全部被忽略,导致无法使用索引。
这里的匹配原因,需要知道MySQL索引底层数据结构,深究原因可以参考文章 InnoDB中索引的推演
4. 主键插入顺序
以InnoDB存储引擎为例,所有数据基于主键去存储,主键储存在数据页中会以从小到大的顺序存储,如果插入的表的主键值不是递增的,数据页自身存在大小,以一个数据页存放100条数据为例,当主键值非递增添加时,会导致数据在各个数据页因为排序去移动,即导致大量的也分裂,这个是非常消耗性能的,建议主键以自增方式储存。
5. 计算、函数、类型转换
当条件中使用计算如加,减之类 where id+1=1000,或者使用函数如 where SUBSTRING(name)=‘zs’,或者类型转换如id为int类型,条件使用字符串 where id = ‘100’ 这些情况都会导致索引失效。
6. 范围条件右边的列索引失效
如一张表仅有一个索引且为组合索引,字段排序为 id,name,age,address 查询条件为 where id=1 and name=‘zs’ and age>20 and address=‘sh’ 这时上面的组合索引会被使用到,但匹配到的索引字段只有id,name,age这三个,address因为age为范围判断条件使得无法匹配索引。 若查询条件为 where id>1 and name=‘zs’ and age=20 and address=‘sh’ 这时只有id这个字段可以匹配索引,其余在id右边的索引字段都会失效。 针对此种情况,建议把范围索引字段放在组合索引的最后。
7. 不等于(!= 或 <>)索引失效
如where id !=1 或 where id <> 1 这种情况 id 无法匹配到索引。
8. is null 可以使用索引,is not null 无法使用索引,not like 无法使用索引
针对这种情况,建议在设计数据表时将字段设置为NOT NULL约束,如INT类型字段,可以默认值设置为0。
9. like 以通配符%开头索引失效
如条件1:where name like ‘%zs%’ 条件2:where name like ‘zs%’ 结果:条件1无法使用索引,条件2可以使用索引
10. or 前后存在非索引列,索引失效
如有一张表仅有一个索引 index_age,查询条件为 where age = 20 or name = ‘zs’,这时无法匹配到索引。如果在针对name字段建一个索引 index_name,这个查询条件便可以匹配到索引。
11. 数据库和表的字符集统一使用utf8mb4
统一使用uft8mb4兼容性比较好,统一字符集可以避免由于字符集转换产生的乱码,也可以避免不同的字符集进行比较前需要进行转换导致索引失效。
问题
- 组合索引中字段是排序的比如,索引id,name,age,address ,我们在使用时必须也要照这个排序吗?
实际使用中,字段先后都可以,SQL执行后会优化器对其进行优化的。
|