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

MySQL索引诊断实战:从SHOW INDEX结果解读到性能优化

1. 为什么需要关注SHOW INDEX结果

当你发现MySQL查询突然变慢时,第一反应可能就是"加个索引试试"。但实际情况往往更复杂——已有的索引可能根本没被使用,或者使用方式不对。我遇到过不少案例,数据库里堆了十几个索引,查询速度却越来越慢。这时候SHOW INDEX就是你的手术刀,能精准解剖索引问题。

上周排查的一个电商系统案例就很典型:订单表有2000万数据,用户反馈历史订单查询要15秒才能返回。打开SHOW INDEX FROM orders一看,发现有个联合索引的Cardinality值异常低,只有个位数。这意味着这个索引的区分度几乎为零,就像用"性别"字段查人一样低效。

2. SHOW INDEX结果深度解析

2.1 关键字段解读指南

执行SHOW INDEX FROM your_table会返回这样的结构(以MySQL 8.0为例):

mysql> SHOW INDEX FROM employees; +-----------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-----------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | employees | 0 | PRIMARY | 1 | emp_no | A | 299512 | NULL | NULL | | BTREE | | | | employees | 1 | idx_name | 1 | first_name | A | 1275 | NULL | NULL | | BTREE | | | | employees | 1 | idx_name | 2 | last_name | A | 2774 | NULL | NULL | YES | BTREE | | | +-----------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

需要特别关注的几个黄金指标:

  • Cardinality(基数):这个值表示索引列中不重复值的预估数量。基数与表行数的比值越接近1,索引效果越好。比如主键的基数就等于表总行数。

  • Collation(排序规则):A表示升序,当你看到A DESC这样的混合排序时,要注意排序方向是否与你的ORDER BY子句匹配。

  • Sub_part(前缀索引长度):如果是字符串字段的前缀索引,这里会显示截取的长度。我曾见过用前5个字符做用户名索引导致大量冲突的情况。

2.2 隐藏的陷阱字段

有些字段容易被忽略但很关键:

  • Null字段:显示为YES时,说明该列允许NULL值。要注意NULL值不会被计入普通索引,这也是为什么WHERE col IS NULL有时不走索引。

  • Packed字段:显示索引是否被压缩。使用压缩索引虽然节省空间,但会增加CPU开销。

  • Index_type:最常见的是BTREE,但全文索引会是FULLTEXT。去年我遇到一个性能问题,就是因为开发者在普通字段上误建了FULLTEXT索引。

3. 实战诊断:从SHOW INDEX发现问题

3.1 识别低效索引

通过这个SQL可以快速找出低效索引:

SELECT table_name, index_name, column_name, cardinality, table_rows, ROUND(cardinality/table_rows*100,2) AS selectivity FROM information_schema.statistics JOIN information_schema.tables USING (table_schema, table_name) WHERE table_schema = 'your_db' AND table_rows > 0 ORDER BY selectivity;

经验阈值

  • 选择性<5%:考虑删除或重建索引
  • 5%-30%:中等效果,看业务场景决定
  • 30%:优质索引

3.2 揪出重复索引

重复索引不仅浪费空间,还会降低写入性能。用这个查询检测:

SELECT a.table_name, a.index_name AS duplicate_index, b.index_name AS dominant_index, a.column_name FROM information_schema.statistics a JOIN information_schema.statistics b ON a.table_schema = b.table_schema AND a.table_name = b.table_name AND a.seq_in_index = b.seq_in_index AND a.column_name = b.column_name WHERE a.table_schema = 'your_db' AND a.index_name != b.index_name AND a.seq_in_index = 1 ORDER BY a.table_name, a.index_name;

常见模式是既有单列索引又有包含该列的联合索引,通常可以删除单列索引。

4. 性能优化实战方案

4.1 索引碎片整理

当Cardinality值明显低于预期时,可能是索引碎片导致。执行这两个操作:

-- 更新统计信息 ANALYZE TABLE your_table; -- 重建索引(InnoDB) ALTER TABLE your_table ENGINE=InnoDB;

上周处理的一个案例:某表Cardinality从320万降到87万,重建后查询速度从2.1秒降到0.3秒。

4.2 联合索引优化技巧

通过SHOW INDEX的seq_in_index字段,可以分析联合索引的列顺序是否合理。黄金法则:

  1. 高区分度列放前面
  2. 等值查询列优先于范围查询列
  3. 经常排序的列要包含在索引中

比如看到这样的索引:

idx_mixed (gender, birth_date, salary)

明显不合理,因为gender区分度太低。应该调整为:

idx_mixed (birth_date, salary, gender)

5. 高级技巧:结合执行计划分析

SHOW INDEX只是诊断的第一步,结合EXPLAIN才能完整分析。重点关注:

  • possible_keys和key的差异:为什么没走预期的索引?
  • key_len:实际使用的索引长度,判断是否用到索引的全部部分
  • Extra列:是否出现Using filesort或Using temporary

一个真实案例:某查询执行计划显示用了索引,但key_len只有4(int类型长度),而联合索引总长度应该是8。这说明只用了联合索引的第一列,调整查询条件后性能提升6倍。

6. 自动化监控方案

建议定期运行以下监控脚本:

SELECT table_schema, table_name, index_name, ROUND(data_length/1024/1024,2) AS size_mb, ROUND(data_free/1024/1024,2) AS free_mb, ROUND(data_free/(data_length+data_free)*100,2) AS frag_ratio FROM information_schema.tables JOIN information_schema.statistics USING (table_schema, table_name) WHERE table_schema NOT IN ('mysql','information_schema') AND data_free > 0 ORDER BY frag_ratio DESC LIMIT 10;

报警阈值建议

  • 碎片率>30%:需要立即优化
  • 碎片率>15%:列入维护计划
  • 索引大小超过数据大小50%:检查索引合理性

7. 避坑指南

这些年踩过的坑总结:

  1. 前缀索引陷阱:用前N个字符做索引时,一定要测试区分度。曾见过用手机号前7位做索引,结果10万用户中有8万重复。

  2. 外键索引遗漏:创建外键不会自动建索引,导致级联更新变慢。

  3. JSON字段索引:MySQL 8.0支持JSON字段索引,但要注意只对完整路径生效。

  4. 隐式类型转换:varchar字段用数字查询会导致索引失效,SHOW INDEX能看到但实际用不上。

  5. 统计信息过时:大表批量操作后,记得手动执行ANALYZE TABLE更新Cardinality值。

http://www.jsqmd.com/news/1186654/

相关文章:

  • 二、Ubuntu 18.04 服务器从零部署与安全初始化(SSH、网络与防火墙)
  • 最新靠谱的煎药机平台推荐 6个口碑维度拆解参考 - 资讯快报
  • AI+行业落地:四大垂直领域智能化解决方案
  • WarcraftHelper终极指南:5分钟让经典魔兽焕发新生
  • 交换机堆叠和级联到底有什么区别?很多网络工程师刚入行都容易弄混
  • 数据科学家面试四维校验法:问题定义、技术决策、协作解码与系统韧性
  • Qt面试进阶:从30道基础题到核心机制深度剖析
  • 如何快速掌握CodeQL:安全研究者的代码安全分析实战指南
  • 3个技巧快速掌握bge-small-zh-v1.5:中文语义搜索从入门到精通
  • 企业AI到底是什么?
  • 2026沈阳闲置黄金变现优选 合扬连锁黄金回收门店完整清单 - 开心测评
  • Whois 域名查询 API 的调用限制与用量边界说明
  • 一文搞懂【知识蒸馏】核心算法与实战调优
  • LangChain Agent 实战:从零构建一个多工具智能体
  • 艺镜AI 3D导演台:文本生成3D场景的核心功能与实战指南
  • linux | zlib源码编译与多发行版安装指南
  • TPS7A53-Q1汽车级LDO深度解析:3A大电流下的超低噪声电源设计
  • AI代理实战指南:从零构建自动化工作流与工程化部署
  • GNSS和单北斗变形监测在桥梁领域的应用与发展分析
  • 构建高性能VSCode图标扩展架构:依赖注入与配置驱动的技术实现
  • 【通信系统仿真系列】基于Walsh码正交性与BPSK调制的多用户CDMA系统误码率极限分析
  • CVAT标注平台深度解析:企业级数据标注的高效解决方案
  • MySQL锁机制的深度剖析:从MDL到行锁的兼容矩阵与死锁检测算法全景解读
  • SUI:打造你的专属服务器启动页和新标签页终极指南
  • BPF应用CPU分析:profile、threaded与火焰图
  • n8n与大模型构建零代码图片识别系统
  • 自考论文写作工具全攻略:从选题到答辩
  • TAS5414C-Q1与STM32F415RG芯片对比:音频处理与嵌入式控制
  • 如何快速掌握Gemini CLI:面向新手的完整智能助手指南
  • 5分钟找回你的QQ空间记忆:GetQzonehistory数据恢复指南