mysql中索引的大小与性能的平衡

发布时间 - 2026-01-10 00:00:00    点击率:
索引字段越短、B+树层级越浅,磁盘I/O越少;前缀索引、联合索引顺序、索引数量、覆盖索引冗余、唯一索引锁机制均需权衡读写性能。

索引字段越短,B+树层级越浅

MySQL 的 PRIMARY KEY 和二级索引都基于 B+ 树,树的高度直接决定磁盘 I/O 次数。每层节点能存的键值数量,和单个索引项大小强相关:字段越长(比如用 VARCHAR(255) 存邮箱但只用前 20 位区分),页内能放的键就越少,树就更容易变高。

实操建议:

  • 对字符串字段建索引时,优先考虑 INDEX (email(32)) 而非全字段,前提是业务上前 N 位已具备足够区分度
  • 避免在 TEXT 或长 VARCHAR 上直接建普通索引;若必须搜索,改用前缀索引或倒排(如 FULLTEXT
  • 联合索引中把等值查询字段放前面,排序/范围字段放后面——顺序错会导致索引截断失效

索引不是越多越好,写放大和内存压力会反噬读性能

每次 INSERT/UPDATE/DELETE 都要同步更新所有相关索引。一个表有 5 个索引,写操作实际可能触发 5 次 B+ 树分裂+页写入。更隐蔽的问题是:索引总大小超过 innodb_buffer_pool_size,会导致频繁换页,SHOW ENGINE INNODB STATUS 中能看到大量 Pages made youngPages read ahead 异常值。

判断依据:

  • SELECT SUM(index_length) FROM information_schema.TABLES WHERE table_schema = 'db' AND table_name = 't'; 查索引总字节数
  • 对比 SHOW VARIABLES LIKE 'innodb_buffer_pool_size';,若索引体积 > 70% 缓冲池,就要警惕
  • 慢查日志里反复出现 Using index condition 却仍慢,可能是索引太多导致缓存命中率低

覆盖索引能省掉回表,但字段冗余会拖慢写入和备份

覆盖索引(SELECT a,b FROM t WHERE a=1,且 INDEX(a,b) 存在)确实避免了聚簇索引回查,但 b 字段被重复存两份:一份在聚簇索引叶子页,一份在二级索引叶子页。这意味着:

  • 插入一行,b 值要写两次;更新 b,也要同步改两个位置
  • mysqldump 或物理备份时,数据文件体积增大,网络传输和恢复时间拉长
  • 如果 bJSON 或大文本,这种冗余代价远超查询收益

权衡做法:

-- 好:高频查询且 b 很小(如 status TINYINT)
CREATE INDEX idx_a_b ON t(a, b);

-- 小心:b 是 VARCHAR(500) 或 TEXT -- 更优解:只建 idx_a,用 JOIN 或应用层二次查询补 b

唯一索引和普通索引在并发写入时表现不同

唯一索引(UNIQUE KEY)要求插入前做唯一性校验,InnoDB 必须加 next-key lock 锁住插入间隙;而普通索引只需在插入后加记录锁。高并发 INSERT 场景下,前者更容易引发锁等待甚至死锁。

典型现象:

  • 批量导入时,Duplicate entry 报错少但 Lock wait timeout 多 → 可能是唯一索引锁冲突
  • INSERT ... ON DUPLICATE KEY UPDATE 时,唯一索引会强制走唯一扫描,比普通索引多一次查找
  • 如果业务能接受应用层去重(如先 SELECTINSERT),有时宁可去掉唯一约束,靠代码逻辑保一致性

真正难平衡的,从来不是“要不要加索引”,而是“这个索引在最差写负载下,会让主库延迟多少秒”。线上调优时,pt-index-usagesys.schema_unused_indexes 只能告诉你“没用过”,没法告诉你“加了会不会拖垮写入”。得看 SHOW PROFILE FOR QUERY 里的 innodb_rows_inserted 和锁等待时间。


# mysql  # js  # json  # 字节  # ai  # 邮箱  # for  # select  # 字符串  # using  # delete  # 并发  # 告诉你  # 死锁  # 越少  # 应用层  # 太多  # 都要  # 也要  # 只需  # 会不会  # 两次 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 高性能网站服务器配置指南:安全稳定与高效建站核心方案  韩国服务器如何优化跨境访问实现高效连接?  android nfc常用标签读取总结  Laravel路由Route怎么设置_Laravel基础路由定义与参数传递规则【详解】  文字头像制作网站推荐软件,醒图能自动配文字吗?  中山网站制作网页,中山新生登记系统登记流程?  Python文件流缓冲机制_IO性能解析【教程】  Laravel中的Facade(门面)到底是什么原理  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  JS去除重复并统计数量的实现方法  制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?  零基础网站服务器架设实战:轻量应用与域名解析配置指南  Android实现代码画虚线边框背景效果  Python制作简易注册登录系统  成都网站制作公司哪家好,四川省职工服务网是做什么用?  如何生成腾讯云建站专用兑换码?  如何挑选最适合建站的高性能VPS主机?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  微信小程序 配置文件详细介绍  如何快速重置建站主机并恢复默认配置?  Laravel如何实现数据库事务?(DB Facade示例)  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)  再谈Python中的字符串与字符编码(推荐)  如何快速完成中国万网建站详细流程?  如何快速搭建高效可靠的建站解决方案?  免费网站制作appp,免费制作app哪个平台好?  如何自定义建站之星模板颜色并下载新样式?  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?  Win11怎么关闭资讯和兴趣_Windows11任务栏设置隐藏小组件  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  作用域操作符会触发自动加载吗_php类自动加载机制与::调用【教程】  Android自定义listview布局实现上拉加载下拉刷新功能  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  微信小程序制作网站有哪些,微信小程序需要做网站吗?  Linux后台任务运行方法_nohup与&使用技巧【技巧】  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  Python正则表达式进阶教程_复杂匹配与分组替换解析  微信小程序 五星评分(包括半颗星评分)实例代码  如何在阿里云完成域名注册与建站?  ,在苏州找工作,上哪个网站比较好?  Win11怎么设置虚拟桌面 Win11新建多桌面切换操作【技巧】  Laravel如何处理表单验证?(Requests代码示例)  北京专业网站制作设计师招聘,北京白云观官方网站?  如何为不同团队 ID 动态生成多个独立按钮  rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  Laravel Seeder填充数据教程_Laravel模型工厂Factory使用  网站页面设计需要考虑到这些问题