分享
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
极客时间训练营-MySQL 进阶训练营
获课♥》itazs.fun/15853/
MySQL 索引失效的 5 大场景及避坑指南
场景一:违反最左前缀原则
原理:对于联合索引(多列组成的索引),MySQL 会按照索引定义的列顺序从左到右依次使用索引。如果查询条件中跳过了联合索引的某一列,那么该列及后面的列索引将失效。
示例:假设有一个联合索引 (name, age, gender),执行查询 SELECT * FROM users WHERE age = 25 AND gender = 'male';,由于跳过了 name 列,age 和 gender 列的索引将失效。
避坑指南:在设计联合索引时,要根据查询条件合理确定列的顺序,将最常用于查询过滤的列放在前面。编写查询语句时,确保查询条件按照联合索引的列顺序从左到右依次出现。
场景二:在索引列上使用函数或进行计算
原理:当在索引列上使用函数或进行计算时,MySQL 无法直接使用索引进行快速查找,因为索引是基于原始列值构建的,函数或计算会改变列值的原始形态。
示例:有一个索引 (create_time),执行查询 SELECT * FROM orders WHERE DATE(create_time) = '2023年01月01日';,由于对 create_time 列使用了 DATE() 函数,索引将失效。
避坑指南:尽量避免在索引列上使用函数或进行计算。如果需要对日期进行查询,可以调整查询条件,例如 SELECT * FROM orders WHERE create_time >= '2023年01月01日 00:00:00' AND create_time < '2023年01月02日 00:00:00';。
场景三:使用不等于(!= 或 <>)、NOT IN、NOT LIKE 等操作符
原理:这些操作符会导致 MySQL 无法使用索引进行范围查找,只能进行全表扫描。因为索引是基于有序的数据结构构建的,而不等于、不在某个范围内等操作无法利用这种有序性。
示例:有一个索引 (status),执行查询 SELECT * FROM tasks WHERE status != 'completed';,索引将失效。
避坑指南:尽量避免使用这些操作符。如果必须使用,可以考虑将查询条件改写为使用 IN 或范围查询。例如,对于上面的例子,可以改写为 SELECT * FROM tasks WHERE status IN ('pending', 'in_progress');(假设 status 只有这几种取值)。
场景四:使用 OR 连接条件且其中一个条件没有索引
原理:当使用 OR 连接多个查询条件时,如果其中一个条件没有索引,MySQL 为了保证查询结果的正确性,会放弃使用其他有索引的条件,而选择全表扫描。
示例:有一个索引 (username),但 email 列没有索引,执行查询 SELECT * FROM users WHERE username = 'john' OR email = 'john@example.com';,由于 email 列没有索引,username 列的索引也将失效。
避坑指南:尽量确保 OR 连接的所有条件都有索引。如果无法做到,可以考虑将查询拆分为多个查询,然后使用 UNION 合并结果。例如,上面的例子可以拆分为 SELECT * FROM users WHERE username = 'john' UNION SELECT * FROM users WHERE email = 'john@example.com';。
场景五:数据类型不匹配
原理:当查询条件中的数据类型与索引列的数据类型不匹配时,MySQL 会进行隐式类型转换,这会导致索引失效。
示例:有一个索引 (user_id),其数据类型为 INT,但执行查询 SELECT * FROM users WHERE user_id = '123';,由于查询条件中的 '123' 是字符串类型,MySQL 会将其转换为整数类型,但在这个过程中索引会失效。
避坑指南:确保查询条件中的数据类型与索引列的数据类型一致。在编写查询语句时,注意数据类型的匹配,避免使用引号将数字类型的值括起来(除非确实需要字符串比较)。
总结
索引设计:合理设计联合索引的列顺序,根据查询频率和选择性来确定。
查询优化:避免在索引列上使用函数、计算、不等于等操作符,以及 OR 连接无索引条件和类型不匹配的查询。
定期维护:定期分析表的索引使用情况,通过 EXPLAIN 命令查看查询执行计划,及时发现索引失效的问题并进行优化。同时,根据业务变化和数据增长情况,适时调整索引策略。
举报/反馈
相关搜索
MySQL进阶教程
有疑问加站长微信联系(非本文作者))
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信515 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传