前言我们已经讲解了SQL优化的大致流程,无论是优化join语句、where语句、聚合函数还是排序操作,核心都是利用索引来优化sql语句,但是大家认为我们为字段创建了索引之后,索引就一定生效了吗?当然不是,因为索引可能会失效。为什么索引会失败?失败的后果是什么?本节我们使用当前的问题,即查询千万级订单表耗时3秒。让我们通过这个问题来一探究竟。至此,我们已经初步确定了问题的原因。说白了,SQL一般是不使用索引的,因为单表几千万条数据,B+树基本也就三四层。如果正常使用索引,sql执行需要几十毫秒。所以这个sql一定不能使用索引。说白了就是索引无效。这时候会发生大量的磁盘IO,最终导致sql查询时间达到3s。索引失败的后果是什么?首先我们来看一下如果索引失效会发生什么情况?让我们以上一篇文章中出现的图表为例。我们可以看到,一个数据表中的数据存放在多个数据页中,数据页之间通过双向链表连接。以订单表为例。如果订单表中的数据达到千万级数据,此时存储订单数据的数据页数量不下100个数据页,可能有几万甚至几千万条数据页。如果不使用索引,就意味着我们要面临加载几万甚至几十万数据页的风险。这个过程也会造成大量的磁盘IO,非常消耗性能,影响我们查询的效率。因此,我们也可以知道,为什么随着表的数据量越来越大,查询速度会越来越慢。这时候,索引就变得越来越重要了。关键在于我们如何优化我们的sql语句,让sql语句在查询数据的时候尽量使用索引来查询数据。sql优化案例实战体验下无索引查询效率在sql优化之前,先来体验一下我们的sql在没有索引的情况下的查询效率。(1)无索引查询效率该表当前数据量2500W,查询时间已消耗65秒(2)无索引执行计划通过explain分析查询sql的执行计划,可以看出这个sql已经执行了全表扫描。(3)sql执行慢会产生什么样的连锁反应?在模拟并发请求时,会发现由于SQL查询时间过长,数据库连接数被快速消耗,最终再次执行后续SQL时连接会被拒绝。体验使用索引的查询效率(1)创建索引,我们可以在order_no字段上加一个索引,如下图:(2)使用索引的查询效率在order_no字段上加一个索引,然后尝试查询以查看它的效率提高了多少。我们可以发现,同一个没有索引的sql和有索引的sql查询效率差距非常大。因此,在大表查询慢的情况下,不妨查看查询字段是否添加了合适的索引。(3)带索引的执行计划通过执行计划可以看到,加了索引后,只需要扫描一行就可以找到需要查询的数据,订单号的类型是String。SQL语句写对了,查询效率是非常快的。(2)隐式转换导致索引失败。查询时间。通过图中的执行情况,执行效率确实相差很大,查询时间足足有24秒!(3)通过explain查看索引失效的执行计划通过explain分析这条SQL的执行计划,我们会发现虽然我们在order_no字段上设置了索引,但是这条查询还是进行了全表扫描。说白了,根本没用。到索引,那么查询效率会大大降低。结束语最后简单说明一下,实际的sql优化是比较复杂的,可能还涉及到锁、内存和网络。这里我们只列出sql优化需要注意的两点,这两点只是sql优化的一小部分。之所以提出这两点,主要是为了达到引玉的效果,即大家遇到问题首先应该把注意力放在SQL优化上,而不是先去想一些高层次的解决方案。
