目录
- 前言
- 调优过程
- 总结
前言
环境:MySQL 5.6、windows 11
前阵子,有一个 BI 看板跑不起来,每次执行跑了很久,还不一定有结果,急需维护迭代。
经过调试,发现看板的SQL 逻辑中有一个开销非常大的逻辑影响了整个 SQL 的逻辑。
抽象出来讲就是,有两个表暂且叫t1
和t2
吧,两个表都有用户的两个标识,一个是uid
,另一个是mobile
。t1
表中的uid
和mobile
字段都有可能是空字符串,但至少有一个值;而t2
表都有uid
,但是mobile
字段可能为空字符串。
现在的目的就是将两个表进行关联,最大化的获取到uid
和mobile
的值,以保证数据的准确性和完整性。
补充说明:t1
表的数据量是万级别,mobile=''
大约一两百个;而t2
表的数据量是千万级别,70% 的mobile
为空。两个表的相关字段都有索引。
原先的逻辑大致如下:
-- sql1:
SELECT IF(t1.uid='',t2.uid,t1.mobile) uid,IF(t1.mobile='',t2.mobile,t1.mobile) mob
FROM t1
LEFT JOIN t2 ON (t1.uid !='' AND t1.uid=t2.uid) or (t1.mobile !='' AND t1.mobile=t2.mobile)
limit 200;
通过LEFT JOIN
进行关联,关联条件使用了OR
进行连接,每一个独立的条件里分别还有一个AND
判断。
执行策略简化之后大致如下(局部调整):
执行计划是树状结构,顺序是从下往上看,先是第 8 步,操作策略是TableScan
,即全表扫描,数据量是1.0E7。然后第 7 步进行Exchange[REPLICATE]
,即数据交换操作,将从上一个步骤的单个执行线程复制到多个执行线程,数据量也是1.0E7。可以看到后面是会有一些发散,由 1.0E7 增加到 1.1E7。而且LEFT JOIN
的行数也是大表的数据,而非小表。
由于执行计划是树状结构,仅看到了执行的顺序、操作和数据量,没有像 MySQL 默认的表格形式般展示执行策略。所以更多的是通过执行的时间进一步辅助判断性能。
该逻辑跑了几次没有跑出结果,每次等待了30多秒,最终放弃了。直接改!
调优过程
众所周知,OR
是一个相对较慢的查询优化方案,所以为了保证查询效率,首先要把OR
优化掉,尝试使用LEFT JOIN
来优化。
故分别单独关联一个条件,然后执行查询,观察最终的效果。结果每个任务的执行速度都提升到了一个层次,几百毫秒的功夫便跑完了!
那么,基于以上的观察,一个初步的、可行的方案就浮现出来了,那就是使用LEFT JOIN
的方式,去关联两次t2
表,一次使用uid
来关联,一次使用mobile
来关联。
SELECT t1.uid,t2.mobile FROM t1 LEFT JOIN t2 ON t1.uid=t2.uid AND t1.uid<>'' limit 200;
SELECT t2.uid,t1.mobile FROM t1 LEFT JOIN t2 ON t1.mobile=t2.mobile AND t1.mobile<>'' limit 200;
最终的结果如下:
-- sql2:
SELECT IF(t1.uid='',t2_2.mobile,t1.mobile) uid,IF(t1.mobile='',t2.uid,t1.uid) mob
FROM t1
LEFT JOIN t2 ON t1.uid=t2.uid
LEFT JOIN t2 t2_2 ON t1.mobile=t2_2.mobile AND t2.uid IS NULL
简单分析下:
- 先看关联逻辑,都是使用
LEFT JOIN
,优先采用关联t1.uid
,再关联t1.mobile
。- 第一个
LEFT JOIN
由于t1.uid
90% 不为空,所以直接关联,把分步测试的t1.uid<>''
限制条件去掉,减少一次较低效判断的开销。 - 第二个
LEFT JOIN
同理,把t1.mobile<>''
去掉了,但是加了另外一个条件AND t2.uid IS NULL
,将匹配的数据量降低到原来的 10%(10% 有mobile
无uid
)。
- 第一个
- 关于
SELECT
有一个容易绕的逻辑,就是通过t1.uid
匹配上的则取t2.mobile
,通过t1.mobile
匹配上的则取t2.uid
,如果绕不过来,可以细品一下。
最终跑了很多次,执行时间是几百毫秒到1秒,不等,会受到网络波动和资源调配的影响,不过基本就是不超过 1 秒。
总结
其实,调优通常要考虑到运行环境,包括网络速度、系统配置等多种影响因素;除了环境之外,运行时长也十分关键,运行时间太长往往意味着资源的开销会更多;此外,理解表单逻辑,把握数据表单之间的联系,也需要重点关注,这有助于我们更好地解决问题。
因此,调优的过程中,我们需要结合以上诸多因素进行综合判断,关键在于灵活运用,学以致用,以期达到更佳的效果。