当前位置: 首页 > news >正文

MySQL索引调优之索引顺序是否应该“匹配查询书写顺序”?

✅ 结论先行:

不会更好,反而可能更差!

你原来的索引顺序是:

idx1: (res_speciality_id, ph_status, del_flag, is_delete, manage_stage)

你想改成:

idx2: (res_speciality_id, manage_stage, ph_status, del_flag, is_delete)

👉 推荐保持原顺序(idx1,原因如下:


🔍 一、索引顺序的核心原则:选择性 + 等值 vs 范围

复合索引的设计原则是:

把“高选择性”的等值字段放前面,范围字段(如 IN, >, <)尽量往后放

你的字段分析:

字段类型选择性是否等值建议位置
res_speciality_id= '231'高(过滤90%+)✅ 等值第1位
ph_status= '2'✅ 等值第2位
del_flag= '1'✅ 等值第3位
is_delete= '0'✅ 等值第4位
manage_stageIN (1,2)⚠️ 范围最后一位

✅ 正确顺序(原索引):

(res_speciality_id, ph_status, del_flag, is_delete, manage_stage)
  • 前4个都是等值条件,可以连续使用索引
  • 最后一个是范围条件,放在最后是最佳实践

❌ 你提议的顺序:

(res_speciality_id, manage_stage, ph_status, del_flag, is_delete)
  • 第2位就是 IN (1,2) 范围查询
  • 一旦遇到范围查询,后面的字段(ph_status, del_flag, is_delete)就无法使用索引了!

🔥 这是关键!MySQL 在复合索引中,范围查询之后的字段无法再使用索引进行查找


🔍 二、为什么 manage_stage IN (1,2) 是“范围查询”?

虽然 IN (1,2) 看起来像等值,但在 MySQL 中,它被当作范围扫描(range scan)

一旦使用 IN,索引的后续字段只能用于“索引条件下推(ICP)”,而不能用于“索引定位”。


🔍 三、举个例子说明

假设你用新索引:

(res_speciality_id, manage_stage, ph_status, del_flag, is_delete)

查询:

WHERE res_speciality_id = '231'AND manage_stage IN (1, 2)AND ph_status = '2'  -- ❌ 这个字段无法用于索引定位!

MySQL 的执行过程:

  1. res_speciality_id = '231' 定位
  2. 在这个范围内,扫描所有 manage_stage IN (1,2) 的记录
  3. 对于每一条匹配的记录,再检查 ph_status = '2' 是否成立
    • ph_status 已经在索引中,只是不能用于“跳过”数据
    • 它只能通过 ICP 在索引层过滤,但无法减少索引扫描范围

→ 相比之下,原索引能用 ph_status 进一步缩小搜索范围。


🔍 四、EXPLAIN 验证预期

索引顺序key_len能使用的字段说明
(res, ph, del, is_del, m_stage)较长全部5个字段m_stage 在最后,前4个等值字段都能用于定位
(res, m_stage, ph, del, is_del)相同只有前2个用于定位,后3个只能ICPm_stage 是范围,后面的字段“失效”

✅ 五、你的“查询顺序一致”想法为什么不对?

你看到查询是:

AND res_speciality_id = '231'
AND manage_stage IN (1, 2)
AND ph_status = '2'
...

所以觉得索引也该这么排。

MySQL 优化器不看 SQL 书写顺序,它会自动重排条件,按索引定义顺序去匹配最左前缀。

所以:

  • 索引顺序决定执行路径
  • SQL 书写顺序无关紧要

✅ 六、最佳实践总结

✅ 正确的复合索引设计原则:

  1. 等值字段(=)放前面,按选择性从高到低排序
  2. 范围字段(IN, >, <, BETWEEN)放最后
  3. 不要把范围字段插在中间,否则后面的字段无法用于索引定位

✅ 你的原索引是正确的:

(res_speciality_id, ph_status, del_flag, is_delete, manage_stage)
  • ✅ 高选择性等值字段在前
  • ✅ 所有等值字段连续
  • ✅ 范围字段 manage_stage IN (1,2) 在最后

✅ 七、建议

保持原索引不变,不要把 manage_stage 提前。

如果你真想验证,可以:

  1. 创建新索引
  2. EXPLAIN 对比 key_lenrows
  3. 你会发现原索引的 rows 更小或相等,但更稳定

🎯 总结一句话:

索引设计应基于“数据访问模式”和“字段类型”,而不是 SQL 的书写顺序。

http://www.dtcms.com/a/462754.html

相关文章:

  • 安阳网站建设开发用五百丁做名字的简历网站
  • 企业做网站的注意事项沈阳商城网站开发
  • 堆:数组中的第K个最大数
  • 如何添加网站 ico图标小游戏开发需要多少钱
  • printf输出乱码的解决办法
  • 汕头做网站优化的公司两个wordpress
  • 网站域名在哪里如何建立一个免费的网站
  • 重庆交通建设监理协会网站建设银行招标网站
  • 温州企业自助建站系统虚拟主机怎么设计网站吗
  • 网站备案表是什么纪检监察网站建设背景
  • FDC1004学习笔记二:读写数据
  • 双剑合璧:Microsoft Agent Framework——Python与.NET的AI智能体协奏曲
  • 行动比空想更有力量。哪怕只是一小步,也是通向目标的开始。
  • 学习笔记--分页查询 条件分页查询
  • 东莞网络推广网站部门网站建设管理
  • 流式推理 vs 训练模式详细对比
  • 一个酷炫的烟花网站
  • 【AES加密专题】2.AES头文件详解
  • 腾讯员工月薪多少郴州网站seo
  • 网站建设培训个人网络服务器
  • STM32H743-ARM例程14-FATFS
  • 具有营销型网站的公司有哪些网页设计个人简介代码
  • 网站的交互体验网站备案单位的联系方式
  • 百度logo在线设计生成器seo关键词推广公司
  • 网站开发维护公司前端很难学吗
  • 为你的Hugo博客站创建WordCloud标签云
  • .net网站开发免费教程重庆招聘信息最新招聘2021
  • 接口测试总结
  • 大模型部署基础设施搭建 - ComfyUI
  • 做拍客哪个网站好wordpress 功能菜单