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子查询调优的主要内容,如果未能解决你的问题,请参考以下文章

Mysql基础调优

当我执行 AJAX 调用以更改查询集时,所有 javascript 都停止在我的子模板上工作

MySQL 查询调优 - 为啥使用变量中的值比使用文字慢得多?

MySQL子查询(六)

MySQL 性能调优——SQL 查询优化

MYSQL数据库性能调优之一:定位慢查询