MySQL子查询调优
Posted A洋槐树
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL子查询调优相关的知识,希望对你有一定的参考价值。
有以下SQL 执行两三个小时无法执行出结果:
性能问题主要集中在红色字体部分:
红色部分表的数据量为40万笔左右,该SQL的返回结果不分页的话为32万多。
结论:
方案1.改写SQL调到10秒左右出结果,但如果取消分页仍然查不出结果。
方案2.改写SQL 调到3秒以内出结果,但也同样存在取消分页仍然查不出结果来。
select * from (
select a.*,e.PAGY_STAT,b.brname,c.SETL_TYPE,c.SETL_SYMBOL,
c.SETL_CYCLE,c.spec_Setl_Day,c.SETL_ACCT_NAME,c.SETL_ACCT_NO,f.MCC_DESC,if (substring(a.mcht_id,1,10)='27272615663','1','0') as IS_CUN_LIANG,d.audit_dt,
if (g.mcht_id is not null,'01','00') as is_huohu,
if (g.FLAG='2' or g.FLAG='0','01','00') as is_high_quality
from pbs_mcht_base_info a
left join ifs_org b on a.MCHT_ORG_ID = b.brcode
left join pbs_mcht_contr_info c on a.mcht_id =c.mcht_id
left join
(SELECT MCHT_ID,SUBSTR(MAX(LAST_UPD_DATE_TIME),1,8) audit_dt FROM pmp_audit_info WHERE AUDIT_STATE='01' GROUP BY MCHT_ID) d
ON d.mcht_id=a.mcht_id
left join (select mcht_id,if(PAGY_MCHT_ID is null or PAGY_MCHT_ID ='','01','00') as PAGY_STAT
from pbs_mcht_base_info) e on a.mcht_id = e.mcht_id
left join pbs_mcht_mcc_info f on a.mcht_Mcc_Code = f.mcc_id
left join rpt_mcht_active_info g on a.mcht_id=g.mcht_id
where 1=1 order by a.mcht_id desc
) aa where 1=1 limit 1,10
1.改写SQL:
1.先将执行速度快的部分作为驱动表,执行速度慢的作为被驱动表做个子查询来提升速度。
2.消除排序
3.结果10秒左右出结果。(会不会觉得很棒?其实这只是个中间过程,还有更好的改写方式如后面一条
SELECT aa.*,bb.audit_dt
FROM (
(SELECT a.*,
e.PAGY_STAT,
b.brname,
c.SETL_TYPE,
c.SETL_SYMBOL,
c.SETL_CYCLE,
c.spec_Setl_Day,
c.SETL_ACCT_NAME,
c.SETL_ACCT_NO,
f.MCC_DESC,
if (substring(a.mcht_id,
1,
10)='27272615663','1','0') AS IS_CUN_LIANG,if (g.mcht_id is NOT null,'01','00') AS is_huohu, if (g.FLAG='2'
OR g.FLAG='0','01','00') AS is_high_quality
FROM pbs_mcht_base_info a
LEFT JOIN ifs_org b
ON a.MCHT_ORG_ID = b.brcode
LEFT JOIN pbs_mcht_contr_info c
ON a.mcht_id =c.mcht_id
LEFT JOIN
(SELECT mcht_id,
if(PAGY_MCHT_ID is null
OR PAGY_MCHT_ID ='','01','00') AS PAGY_STAT
FROM pbs_mcht_base_info) e
ON a.mcht_id = e.mcht_id
LEFT JOIN pbs_mcht_mcc_info f
ON a.mcht_Mcc_Code = f.mcc_id
LEFT JOIN rpt_mcht_active_info g
ON a.mcht_id=g.mcht_id
ORDER BY a.mcht_id DESC
) aa
LEFT JOIN
(SELECT MCHT_ID,
SUBSTR(MAX(LAST_UPD_DATE_TIME),
1,
8) audit_dt
FROM pmp_audit_info
WHERE AUDIT_STATE='01'
GROUP BY MCHT_ID) bb
ON aa.mcht_id=bb.mcht_id
)
WHERE 1=1 limit 1,10;
2.改写SQL:
1.改写有问题的子查询部分
2.结果2秒多出结果。
SELECT *
FROM
(SELECT a.*,
e.PAGY_STAT,
b.brname,
c.SETL_TYPE,
c.SETL_SYMBOL,
c.SETL_CYCLE,
c.spec_Setl_Day,
c.SETL_ACCT_NAME,
c.SETL_ACCT_NO,
f.MCC_DESC,
IF (substring(a.mcht_id,1,10)='27272615663',
'1',
'0') AS IS_CUN_LIANG,
substr(d.LAST_UPD_DATE_TIME,1,8),
IF (g.mcht_id IS NOT NULL,
'01',
'00') AS is_huohu,
IF (g.FLAG='2'
OR g.FLAG='0',
'01',
'00') AS is_high_quality
FROM pbs_mcht_base_info a
LEFT JOIN ifs_org b ON a.MCHT_ORG_ID = b.brcode
LEFT JOIN pbs_mcht_contr_info c ON a.mcht_id =c.mcht_id
LEFT JOIN pmp_audit_info d ON d.mcht_id=a.mcht_id
AND d.AUDIT_STATE='01'
AND d.LAST_UPD_DATE_TIME=
(SELECT max(dd.LAST_UPD_DATE_TIME)
FROM pmp_audit_info dd
WHERE d.mcht_id=dd.mcht_id)
LEFT JOIN
(SELECT mcht_id,
IF(PAGY_MCHT_ID IS NULL
OR PAGY_MCHT_ID ='',
'01',
'00') AS PAGY_STAT
FROM pbs_mcht_base_info) e ON a.mcht_id = e.mcht_id
LEFT JOIN pbs_mcht_mcc_info f ON a.mcht_Mcc_Code = f.mcc_id
LEFT JOIN rpt_mcht_active_info g ON a.mcht_id=g.mcht_id
WHERE 1=1
ORDER BY a.mcht_id DESC) aa
WHERE 1=1 LIMIT 1,
10;
执行计划
待添加。
在执行速度提升和消除排序方面发现明显的性能改善后有点小成就感,但离优秀的人的距离还很远,需要系统的学习一下这方面的知识。
以上是关于MySQL子查询调优的主要内容,如果未能解决你的问题,请参考以下文章
当我执行 AJAX 调用以更改查询集时,所有 javascript 都停止在我的子模板上工作