Mysql一条多表关联SQL把CPU打爆了,如何优化

今天是清明假期的第三天,收到同事的求助,DB的CPU被打爆了!

查看监控,CPU已经被打爆100%

Mysql一条多表关联SQL把CPU打爆了,如何优化_第1张图片

登录mysql,DB无锁阻塞,元凶是一个异常sql,存在39个并发执行。

Mysql一条多表关联SQL把CPU打爆了,如何优化_第2张图片

SQL的明细如下:

select TEMPSALE.USER_ID_BUY,       TEMPSALE.ORDER_AMOUNT,       TEMPSALE.LAST_UPDATED_DATEfrom T_EAC_BU_SG_CO_INFO TSIrightjoin  (select TOI.SALE_PRO_ID,          TOI.USER_ID_BUY,          TOI.ORDER_AMOUNT,          TOI.LAST_UPDATED_DATE   from T_EAC_BU_ORDER_INFO TOI   left join T_EAC_BU_SALE_GOOD_INFO TEC on TOI.SALE_PRO_ID = TEC.SALE_PRO_ID) TEMPSALE on TSI.SALE_PRO_ID = TEMPSALE.SALE_PRO_IDwhere TSI.CAR_ORIGIN_CODE= '000000008671c3180186829f41ad336f' ;                                

首先看看该sql的执行计划吧

相关的表结构如下:

Mysql一条多表关联SQL把CPU打爆了,如何优化_第3张图片

Mysql一条多表关联SQL把CPU打爆了,如何优化_第4张图片

Mysql一条多表关联SQL把CPU打爆了,如何优化_第5张图片

分析:

先来看看正常情况下这条sql单次执行耗时为多少

Mysql一条多表关联SQL把CPU打爆了,如何优化_第6张图片

索引有缺失吗?

相关表的索引创建无大碍,关联字段与where谓词字段都已经创建好了索引。

针对这条异常sql,我们还有优化的空间吗??

解读执行计划,扫描 表别名为 TOI的表,全表扫描估算数据量为514049, Extra  列为 NULL 没有任何的谓词过滤无效数据。扫描后的结果与 表别名为 TEC 的表 Using index (SALE_PRO_ID字段)进行关联。再与 表别名为 TSI 的表 Using where 使用谓词过滤后关联。

执行耗时绝大部分耗时都在第一步与第二步,即 from T_EAC_BU_ORDER_INFO TOI   left join T_EAC_BU_SALE_GOOD_INFO TEC on TOI.SALE_PRO_ID = TEC.SALE_PRO_ID ,在不影响语义的前提下,

我们改写sql把能过滤大部分数据的谓词表提前作为驱动表执行,这样就能最大程度提高执行效率,缩短执行时间了。即,我们将原本 T_EAC_BU_ORDER_INFO 与 T_EAC_BU_SALE_GOOD_INFO 无谓词的关联,改写为 T_EAC_BU_ORDER_INFO 与 T_EAC_BU_SG_CO_INFO 带谓词关联。

Mysql一条多表关联SQL把CPU打爆了,如何优化_第7张图片

改写后的sql

Mysql一条多表关联SQL把CPU打爆了,如何优化_第8张图片

未优化前sql与优化后sql执行时间对比

Mysql一条多表关联SQL把CPU打爆了,如何优化_第9张图片

未优化前sql与优化后sql执行计划对比

Mysql一条多表关联SQL把CPU打爆了,如何优化_第10张图片

至此,原本执行耗时由9秒+的问题sql,优化至0.00秒,性能提升杠杠的。

总结:

1、多表关联,表谓词能提前的提前过滤无效数据

2、多表关联,小表驱动大表

3、大部分sql优化为最佳索引缺失,部分sql优化需要改写sql

你可能感兴趣的:(sql,mysql,数据库)