为什么你的SQL执行很慢
最近看完了丁奇老师在极客时间的课程,不得不说确实干货满满,然后趁着热乎劲顺手又二刷了《MySQL技术内幕》中的部分内容。但很多东西都是零散的,总觉得需要稍微总结一下。那写点什么呢?就从之前经常被问的两道面试题说起吧。
- 如果一条SQL语句执行很慢,你觉得有哪些原因?
- 如果让你给一张表设计索引,你会考虑哪些因素?
SQL语句执行很慢原因分析
先来回答第一个问题,如果一条SQL语句执行会很慢,会有哪些可能的原因。为了方便说明问题,这里先给出建表语句和初始化语句:
CREATE TABLE `t` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`a` int(10) DEFAULT NULL,
`b` varchar(16) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_a` (`a`),
KEY `idx_b` (`b`)
) ENGINE=InnoDB;
insert into t values (null, 1,'1');
insert into t values (null, 2,'2');
insert into t values (null, 3,'3');
1.没走索引
首先,绝大部分人都能想到的一点就是SQL语句没有走索引。明明给相关字段加了索引,可为什么就是不走索引呢?极大概率是因为索引失效了,以下场景都有可能导致索引失效。
1.1对索引字段进行了计算操作
看这个例子:

为什么对索引字段进行了计算操作之后,就不会走索引了呢?
这里我们需要明白,走索引的本质其实是利用了B+树的有序性以便进行快速定位。但是对索引字段进行计算操作之后,有可能会破坏这种有序性(非线性计算),导致无法利用B+树的这一特性,因此优化器会放弃使用B+树的树搜索功能。
注意,这里要特别强调的是,这种情况下优化器只是放弃了树搜索的能力,而并不是一定会放弃走索引。什么意思呢?请继续看这个例子:

你看,在这个例子中,虽然依然对索引字段a做了计算操作,但是最终优化器还是走了索引idx_a。从执行计划还可以看出,优化器对该索引做了全索引扫面,且使用了覆盖索引。之所以没有选择遍历主键索引,是因为辅助索引更小,且可以利用覆盖索引。
所以,正确的姿势应该是这样的,把函数计算放在变量上:

本文探讨了SQL语句执行慢的原因,包括未使用索引、等待锁、刷脏页和执行undo log,并分析了索引设计的重要原则,如考虑区分度、覆盖索引和唯一性。同时,通过实例解释了计算操作、隐式类型转换、like操作、not in操作等如何影响索引的使用。

4597

被折叠的 条评论
为什么被折叠?



