Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

35 | MySQL调优之索引:索引的失效与优化

强制使用期望的索引
查询选择的索引
注意索引失效的情况
覆盖索引的优势
InnoDB的默认索引结构
复合索引的最左匹配原则
Hash索引的范围查询
减小索引字段大小
自增主键的优势
InnoDB中的覆盖索引
建立组合索引
InnoDB与MyISAM存储引擎的索引区别
Hash索引
B+Tree索引
添加create_time进行组合
申请创建新的索引或发现慢SQL日志
被DBA叫去“批评”
思考题
总结
防止索引失效
前缀索引优化
自增字段作主键优化查询
覆盖索引优化查询
MySQL索引存储结构
重建组合索引
经历
索引的失效与优化
MySQL调优之索引

该思维导图由 AI 生成,仅供参考

你好,我是刘超。
不知道你是否跟我有过同样的经历,那就是作为一个开发工程师,经常被 DBA 叫过去“批评”,而最常见的就是申请创建新的索引或发现慢 SQL 日志了。
记得之前有一次迭代一个业务模块的开发,涉及到了一个新的查询业务,需要根据商品类型、订单状态筛选出需要的订单,并以订单时间进行排序。由于 sku 的索引已经存在了,我在完成业务开发之后,提交了一个创建 status 的索引的需求,理由是 SQL 查询需要使用到这两个索引:
select * from order where status =1 and sku=10001 order by create_time asc
然而,DBA 很快就将这个需求驳回了,并给出了重建一个 sku、status 以及 create_time 组合索引的建议,查询顺序也改成了 sku=10001 and status=1。当时我是知道为什么要重建组合索引,但却无法理解为什么要添加 create_time 这列进行组合。
从执行计划中,我们可以发现使用到了索引,那为什么 DBA 还要求将 create_time 这一列加入到组合索引中呢?这个问题我们在第 33 讲中提到过,相信你也已经知道答案了。通过故事我们可以发现索引知识在平时开发时的重要性,然而它又很容易被我们忽略,所以今天我们就来详细聊一聊索引。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文从MySQL索引存储结构、覆盖索引优化查询、自增字段作主键优化查询以及前缀索引优化等方面展开讨论。首先介绍了B+Tree索引和Hash索引的存储结构,以及InnoDB和MyISAM存储引擎对索引的不同处理方式。其次,强调了覆盖索引的优势,通过建立组合索引来避免回表,提高查询性能。此外,指出了使用自增字段作为主键可以提高数据插入效率,避免页分裂的问题。最后,介绍了前缀索引的优化方式,减小索引字段大小以提高查询速度。通过本文的总结,读者可以快速了解MySQL索引的存储结构和优化方法,为数据库查询性能的提升提供了有益的参考。文章还提到了一些索引失效的情况,以及如何强制使用期望的索引。这篇文章对于想要深入了解MySQL索引优化的读者来说是一份有价值的参考资料。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 性能调优实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(39)

  • 最新
  • 精选
  • QQ怪
    回答老师问题: 按照老师的操作了一遍,实验小部分区间是会走order_id索引的,但是查询范围继续增大 ,反而不走索引而是全表扫描,大概我估摸着的是小于全表5分之一区间能够走索引,超过5分之一会全表扫描,可以使用force index(索引名)强制使用该索引,这就是有些sql表开始跑的挺快的,后面越来越慢的原因吧。。但不清楚mysql优化器为啥要这样选择,希望老师解惑?

    作者回复: 因为order_id索引不能覆盖我们要查询的信息,所以在对order_id查询之后还需要一次回表来查找到整行数据,虽然order_id索引是顺序存放的,但是相对于主键id存放的数据顺序是不一致的,所以存在每次回表都是随机获取整行数据,如果在获取大量数据时,通过这种方式获取数据性能肯定是不理想的。 所以mysql一般判断在查询超过整个表20%的数据时,就会考虑使用聚族索引来查找数据,这种方式顺序读取数据的可能性要大于使用辅助索引的随机读。 在查询少量数据的情况下,使用辅助索引性能更加,而查询大量数据时,就未必了。 如果我们发现在查询一定量数据使用辅助索引要比主键索引快,而数据库又没有按照我们期望的去使用辅助索引,则我们可以通过子查询或force index来强制使用辅助索引。

    2019-08-10
    6
    74
  • CCC
    对索引进行函数操作或者表达式计算也会导致索引的失效

    作者回复: 对的,点赞补充

    2019-08-10
    23
  • Loubobooo
    我的想法是,可以利用子查询去减少回表操作,既然有主键自增id,便可以利用聚簇索引的优势来强制走索引。代码方法如下:select * from order_detail where id in (select id from order_detail where order_id between 5000 and 10000)

    作者回复: 思路是对的,这种方式可以解决。

    2019-08-11
    3
    17
  • 张三丰
    ”如果不存在辅助索引,此时会通过查询聚簇索引来统计行数,如果此时正好存在一个辅助索引,则会通过查询辅助索引来统计行数,减少 I/O 操作。“ 这有什么区别吗?都是通过索引统计行数

    作者回复: 区别在于聚簇索引存储了其他数据,而辅助索引只保存了索引列和主键,所以通过查询辅助索引统计行检索的数据量会更少,I/O操作会更少

    2019-10-04
    2
    13
  • 张学磊
    由于是select *操作,所以每条记录都需进行回表,当server层分析器发现between的范围太大时,使用辅助索引存在大量回表操作,所以觉得得不偿失,故而直接使用主键索引。如果想使用我们期望的索引,需要给server层分析器一个hint,force index(idx_order_id)

    作者回复: 分析到位,答案正确。

    2019-08-10
    13
  • man1s
    走主键索引,优化器认为5000数据+回表5000次性能消耗要大于全表扫描 force index

    作者回复: 👍

    2019-09-16
    7
  • 考休
    为什么innodb存储引擎没有支持哈希索引?

    作者回复: innodb不能手动设置哈希索引,但有自适应哈希索引的功能,也就是如果发现树的查询路径太长时,会记录到一个哈希缓存中,这个时候会用到哈希索引。 哈希索引在关键字查询时非常快,但也有很多缺点,例如无法进行范围查询、无法排序等。

    2020-03-10
    2
    6
  • 某、 
    使用某个字段中字符串的前几个字符建立索引?这句不是很明白,能否细讲一下,能否以身份证这个字段作个栗子?

    作者回复: 身份证前几位一般在相同城市或省都是一样的,所以作为前缀索引区分度不大,如果倒序存储,以原来后六位作为首位区分度更大,alert table xxx add index index_idno(idno(6));

    2019-12-05
    2
    5
  • Charles
    想问下老师为什么回表查询的速度会慢于直接用主键查询,因为回表也是使用主键ID去查询的,就算查询的数据量大,用不用子查询都是使用主键ID去回表或是查询,速度应该一样吧

    作者回复: 回表就相当于两次索引树扫描操作了,而主键查询只有一次。

    2019-08-14
    3
    5
  • 张振宇
    老师,没明白开头那段,为什么要添加 create_time 这列进行组合索引啊

    作者回复: 为了避免文件排序的发生。因为查询时我们只能用到status索引,如果要对create_time进行排序,则需要使用文件排序filesort。 filesort是通过相应的排序算法将取得的数据在内存中进行排序,如果内存不够则会使用磁盘文件作为辅助。虽然在一些场景中,filesort并不是特别消耗性能,但是我们可以避免filesort就尽量避免。

    2020-03-10
    2
    4
收起评论
显示
设置
留言
39
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部