当前位置:首页 > 技术分析 > 正文内容

MySQL索引设计的艺术:你的表该建多少个索引才健康?

ruisui883个月前 (04-01)技术分析38

作为程序员,你一定听过这样的矛盾:DBA总想删索引提升写性能,开发总想加索引优化查询速度。一张表到底该建多少个索引?这个让无数团队头疼的问题,今天我们用「空间换时间」的底层逻辑来破解。

作为程序员,你一定听过这样的矛盾:DBA总想删索引提升写性能,开发总想加索引优化查询速度。一张表到底该建多少个索引?这个让无数团队头疼的问题,今天我们用「空间换时间」的底层逻辑来破解。

1.索引的双面性:天使与魔鬼的共生体

索引的价值证明

  • 查询速度提升10-100倍(B+树时间复杂度O(log n))
  • 覆盖索引避免回表(Extra: Using index)
  • 排序优化(避免filesort)

看不见的成本账单

  • 写操作代价:每个INSERT/UPDATE/DELETE需要更新所有相关索引
  • 空间开销:每个二级索引约占用表数据的20%-30%
  • 内存压力:InnoDB缓冲池需要缓存热索引页
  • 维护成本:索引碎片、统计信息更新

2.索引数量的黄金分割线

危险警戒线

  • 超过10个索引:写入性能可能下降50%+
  • 单个索引超过5个字段:联合索引边际效益锐减
  • 重复索引:(a,b)与(a)同时存在

最佳实践区间

  • OLTP系统推荐3-5个精选索引
  • 数据仓库可放宽至7-10个
  • 每个索引不超过3个字段

3.索引设计的六大军规

高频查询优先法则

-- 查询频率统计示例
SELECT query_pattern, COUNT(*) 
FROM slow_query_log
WHERE table_name='orders'
GROUP BY query_pattern 
ORDER BY COUNT(*) DESC LIMIT 5;

联合索引左前缀原则

  • 正确案例:WHERE a=1 AND b>2 ORDER BY c → INDEX(a,b,c)
  • 错误案例:WHERE b=2 AND c=3 → 无法命中上述索引

区分度计算公式

# 字段区分度评估
selectivity = COUNT(DISTINCT column)/COUNT(*)
# 值>30%适合单独建索引

热点数据隔离策略

  • 大字段单独存储(如JSON/text)
  • 冷热数据分离(按时间分表)

索引复用艺术

  • 排序复用:WHERE a=? ORDER BY b → INDEX(a,b)
  • 覆盖查询:SELECT a,b WHERE c=? → INDEX(c,a,b)

动态调整机制

  • 季度索引健康检查
  • 使用ALTER TABLE ... ALGORITHM=INPLACE在线变更

4.实战案例:电商订单表索引优化

原始结构

CREATE TABLE orders (
  id BIGINT PRIMARY KEY,
  user_id INT,
  product_id INT,
  status TINYINT,
  price DECIMAL(10,2),
  created_at DATETIME,
  INDEX idx_user (user_id),
  INDEX idx_product (product_id),
  INDEX idx_status (status),
  INDEX idx_created (created_at)
);

优化方案

-- 删除单列索引
DROP INDEX idx_user, idx_product, idx_status, idx_created;


-- 创建复合索引
ADD INDEX idx_main_query (user_id, status, created_at);
ADD INDEX idx_product_query (product_id, status);
ADD INDEX idx_time_cover (created_at, price);

优化效果

  • 索引数量从4→3
  • 查询性能提升20%
  • 写入速度提高40%

5.索引监控工具箱

索引利用率分析

SELECT OBJECT_NAME, INDEX_NAME, ROWS_READ
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE OBJECT_SCHEMA='your_db';

冗余索引检测

pt-duplicate-key-checker --user=root --password=xxx --database=your_db1.

索引健康度检查

SELECT TABLE_NAME, INDEX_NAME, 
       ROUND(STAT_VALUE*@@innodb_page_size/1024/1024,2) AS MB 
FROM mysql.innodb_index_stats 
WHERE stat_name='size';

6.新时代的索引哲学

当遇到索引抉择困境时,请记住

  • 数据访问模式决定索引形态(而不是表结构)
  • 索引是活的有机体,需要随业务进化
  • 有时候不加索引才是最优解(如极低频查询)

最后送大家一个决策树

是否需要排序? → 是否高频查询? → 字段区分度如何?
   ↓            ↓               ↓
建联合索引     监控观察         拒绝索引

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/3227.html

标签: 查看表索引
分享给朋友:

“MySQL索引设计的艺术:你的表该建多少个索引才健康?” 的相关文章

代码管理-9-gitlab的使用和设置

gitlab使用1、外观设置完成后保存,返回登录页面查看关于注册,有些公司是不允许打开的,,有些人数非常多的公司就需要打开注册的功能,让人员自己注册,我们来给他特定的权限就可以,毕竟人非常多的时候还由我们来给她们注册就非常不现实了,工作量会很大2、自动注册3、组&用户&项目创建组设置组名称、描述等创...

K8S NFS 共享存储

NFS 共享存储前面我们学习了 hostPath 与 Local PV 两种本地存储方式,但是平时我们的应用更多的是无状态服务,可能会同时发布在不同的节点上,这个时候本地存储就不适用了,往往就需要使用到共享存储了,比如最简单常用的网络共享存储 NFS,本节课我们就来介绍下如何在 Kubernetes...

最快清除数组空值?分享 1 段优质 JS 代码片段!

本内容首发于工粽号:程序员大澈,每日分享一段优质代码片段,欢迎关注和投稿!大家好,我是大澈!本文约 600+ 字,整篇阅读约需 1 分钟。今天分享一段优质 JS 代码片段,用最简洁的代码清除了数组中的空值。老规矩,先阅读代码片段并思考,再看代码解析再思考,最后评论区留下你的见解!const arr...

vue打开新窗口并且实现传参,有图有真相

我要实现的功能是打开一个新窗口用来展示新页面,而且需要传参数,并且参数不能显示在地址栏里面,而且当我刷新页面的时候,传过来的参数不能丢失,要一直存在,除非我手动关闭这个新窗口,即浏览器的标签页。通过面向百度编程,发现网上的根本达不到这个效果,而且还都是坑,明明实现不了,还若有其事的写出来,于是我在标...

推荐一个Java微服务商业级Sass开源电商小程序(开源,企业级项目)

使用Java微服务开发,SpringBoot2框架、MyBatis-plus持久层框架、Redis作为缓存、MySql8作为数据库。 前端vuejs作为开发语言,使用uniapp编码,同时支持微信小程序、安卓App、苹果App。 支持集群部署,单机部署。 unimall 针对中小商户、企业和个人消...

企业微信自建应用和消息发送配置对接系统指南

本文介绍企业微信应用创建、消息提醒、自动回复、自定义菜单和服务端接口对接过程。企业微信登录:https://work.weixin.qq.com/企业微信接口对接,应用授权和发送消息代码:https://www.easywechat.com/docs/5.x/wework/oauth一、创建自建应用...