【面试】MySQL 索引失效分析

本贴最后更新于 2016 天前,其中的信息可能已经时异事殊

先看下面的一个示例:

create table test_03( id int primary key not null auto_increment, c1 char(10), c2 char(10), c3 char(10), c4 char(10), c5 char(10) ); insert into test_03(c1, c2, c3, c4, c5) values ('a1', 'a2', 'a3', 'a4', 'a5'); insert into test_03(c1, c2, c3, c4, c5) values ('b1', 'b2', 'b3', 'b4', 'b5'); insert into test_03(c1, c2, c3, c4, c5) values ('c1', 'c2', 'c3', 'c4', 'c5'); insert into test_03(c1, c2, c3, c4, c5) values ('d1', 'd2', 'd3', 'd4', 'd5'); insert into test_03(c1, c2, c3, c4, c5) values ('e1', 'e2', 'e3', 'e4', 'e5'); create index idx_test03_c1234 on test_03(c1, c2, c3, c4); show index from test_03; explain select * from test_03 where c1='a1' and c2='a2' and c3='a3' and c4='a4'; explain select * from test_03 where c4='a1' and c3='a2' and c1='a3' and c2='a4';

mysql01.png

很显然最下面的 SQL 语句并没有按照索引的建立顺序来查询,但是由于 MySQL 优化器对这条 SQL 做了优化,使得优化后的语句和上面的是一样的顺序,这样就能顺利用到索引了!但是由于这样写 SQL 语句还是会让底层做一次 SQL 优化,所以还不如一开始就按照建立索引的顺序来写 SQL。

mysql02.png

上面的 SQL 会导致 c4 这个索引失效,那么如果是 c4 的范围条件写前面呢?同样的道理,SQL 优化器会对 SQL 语句做优化,优化后的语句成了 explain select * from test_03 where c1='a1' and c2='a2' and c3='a3' and c4>'c4'; 所以自然会用到四个索引了!

再看看下面的 order by 的例子,很显然用于查找的索引有两个就是 c1、c2。c3 用于排序了而不是查找,c4 这个索引没有用到:

mysql03.png

所以上面的 SQL 和 explain select * from test_03 where c1='a1' and c2='a2' order by c3; 一样的,和 c4 根本没有关系了

mysql04.png

上面这个例子呢主要是说中间兄弟没了,也就是你都没有给我第三层梯子,我怎么通过第四层排序,所以只能硬着头皮完成任务,那就 Using filesort 呗!

mysql05.png

用到了一个 c1 索引,但是 c2、c3 用于排序,无 filesort

mysql06.png

用了 c1、c2 两个字段索引,但是 c2、c3 用于排序,无 filesort。看看下面这一种情况,为什么 explain select * from test_03 where c1='a1' and c2='a2' and c5='a5' order by c3, c2; 并没有产生文件内排序呢?

mysql07.png

因为 c2 已经是常量了,在已知字段是常量的情况下需要排序吗?肯定不需要。所以即使你写成了 order by c3,c2 但是实际上只是对 c3 排序!

mysql08.png

由上面的例子可以看出,用到了 c1 来查找,c4 由于中间兄弟的消失是失效的索引,c2、c3 用于分组,但是 c2、c3 如果不按照顺序分组的话就基本是是死掉了,出现了 using temporary,这个是什么意思呢?看这个 Explain 中的 Using temporary

group 表面上是分组,分组之前必排序,所以说和 order by 排序的法则和索引优化的原则是一致的!

定值、范围还是排序,一般 order by 是给个范围。group by 基本上都需要进行排序,会有临时表产生

一般性建议:

对于单键索引,尽量选择针对当前 query 过滤性更好的索引

在选择组合索引的时候,当前 Query 中过滤性最好的字段在索引字段顺序中,位置越靠前越好。

在选择组合索引的时候,尽量选择可以能包含当前 query 中的 where 子句中更多字段的索引

尽可能通过分析统计信息和调整 query 的写法来达到选择合适索引的目的

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
zouchanglin
不做一个码农,要做软件工程师 西安

推荐标签 标签

  • Visio
    1 引用 • 2 回帖 • 1 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 298 关注
  • wolai

    我来 wolai:不仅仅是未来的云端笔记!

    2 引用 • 14 回帖 • 1 关注
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    169 引用 • 1527 回帖
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    133 引用 • 895 回帖 • 1 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 651 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 355 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    295 引用 • 750 回帖 • 1 关注
  • Kotlin

    Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,由 JetBrains 设计开发并开源。Kotlin 可以编译成 Java 字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。在 Google I/O 2017 中,Google 宣布 Kotlin 成为 Android 官方开发语言。

    19 引用 • 33 回帖 • 77 关注
  • Vim

    Vim 是类 UNIX 系统文本编辑器 Vi 的加强版本,加入了更多特性来帮助编辑源代码。Vim 的部分增强功能包括文件比较(vimdiff)、语法高亮、全面的帮助系统、本地脚本(Vimscript)和便于选择的可视化模式。

    29 引用 • 66 回帖
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1440 引用 • 10067 回帖 • 492 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    556 引用 • 674 回帖
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 652 关注
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 543 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    951 引用 • 943 回帖
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 163 关注
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 385 关注
  • danl
    164 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖 • 1 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    428 引用 • 1250 回帖 • 597 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖 • 2 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    12 引用 • 54 回帖 • 17 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    9428 引用 • 42929 回帖 • 109 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 297 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 645 关注
  • 百度

    百度(Nasdaq:BIDU)是全球最大的中文搜索引擎、最大的中文网站。2000 年 1 月由李彦宏创立于北京中关村,致力于向人们提供“简单,可依赖”的信息获取方式。“百度”二字源于中国宋朝词人辛弃疾的《青玉案·元夕》词句“众里寻他千百度”,象征着百度对中文信息检索技术的执著追求。

    63 引用 • 785 回帖 • 109 关注