当前位置:   article > 正文

慢查询优化案例之将子查询替换为临时表再与其他表进行表关联_优化器将子查询转换成多表查询

优化器将子查询转换成多表查询

一 问题描述

有个这样的慢查询,执行需要1.8秒,且该慢查询在另一个慢查询中被调用了几十次,执行长达200秒:

  1. SELECT
  2.                                    ce.orgCode,
  3.                                    ce.serialNum
  4.                             FROM
  5.                                    clue ce
  6.                             LEFT JOIN clue pce ON pce.serialNum = ce.parentId
  7.                             LEFT JOIN (
  8.                                    SELECT
  9.                                           ni.nodeCode,
  10.                                    IF (
  11.                                           ni.workActivityID IS NULL,
  12.                                           ce.statusDate,
  13.                                           ni.opreateDate
  14.                                    ) AS 'statusDate'
  15.                                    FROM
  16.                                           nodeInfo ni
  17.                                    LEFT JOIN clue ce ON ni.nodeCode = ce.serialNum
  18.                                    WHERE
  19.                                           (
  20.                                                  ni.workActivityID = 'finish_clue'
  21.                                                  AND ni.nextOperation = '00'
  22.                                                  OR (
  23.                                                         (
  24.                                                                ni.workActivityID = 'four_approve_2'
  25.                                                                AND ni.nextOperation = '4'
  26.                                                         )
  27.                                                         OR (
  28.                                                                ni.workActivityID = 'three_approve_2'
  29.                                                                AND ni.nextOperation = '4'
  30.                                                         )
  31.                                                  )
  32.                                                  OR ce. STATUS IN (
  33.                                                         '251',
  34.                                                         '252',
  35.                                                         '253',
  36.                                                         '254',
  37.                                                         '255',
  38.                                                         '219B'
  39.                                                  )
  40.                                           )
  41.                                    AND ni.nodeCode LIKE 'XS-%'
  42.                                    GROUP BY
  43.                                           ni.nodeCode
  44.                             ) cezt ON cezt.nodeCode = ce.serialNum

执行计划如下:

查看下该表的索引:

发现group by没有走ni的索引nodeInfo_nodeCode。

强制走这个索引后,查询也还是很慢,1.8秒:

单独执行cezt里的这个sql:

  1. SELECT
  2. ni.nodeCode,
  3. IF (
  4. ni.workActivityID IS NULL,
  5. ce.statusDate,
  6. ni.opreateDate
  7. ) AS 'statusDate'
  8. FROM
  9. nodeInfo ni
  10. LEFT JOIN clue ce ON ni.nodeCode = ce.serialNum
  11. WHERE
  12. (
  13. ni.workActivityID = 'finish_clue'
  14. AND ni.nextOperation = '00'
  15. OR (
  16. (
  17. ni.workActivityID = 'four_approve_2'
  18. AND ni.nextOperation = '4'
  19. )
  20. OR (
  21. ni.workActivityID = 'three_approve_2'
  22. AND ni.nextOperation = '4'
  23. )
  24. )
  25. OR ce. STATUS IN (
  26. '251',
  27. '252',
  28. '253',
  29. '254',
  30. '255',
  31. '219B'
  32. )
  33. )
  34. AND ni.nodeCode LIKE 'XS-%'
  35. GROUP BY ni.nodeCode

也不算慢,0.1秒,也是全表扫描的ni,返回1万行数据。

二 优化思路

把这个包含group by的子查询插入到一个临时表里,再和外面的表进行关联

2.1 把以下sql的查询结果放入一个临时表里

示例:

  1. CREATE TABLE baidd_test_20200803 AS
  2. SELECT
  3.                                    ni.nodeCode,
  4.                             IF (
  5.                                    ni.workActivityID IS NULL,
  6.                                    ce.statusDate,
  7.                                    ni.opreateDate
  8.                             ) AS 'statusDate'
  9.                             FROM
  10.                                    nodeInfo ni
  11.                             LEFT JOIN clue ce ON ni.nodeCode = ce.serialNum
  12.                             WHERE
  13.                                    (
  14.                                           ni.workActivityID = 'finish_clue'
  15.                                           AND ni.nextOperation = '00'
  16.                                           OR (
  17.                                                  (
  18.                                                         ni.workActivityID = 'four_approve_2'
  19.                                                         AND ni.nextOperation = '4'
  20.                                                  )
  21.                                                  OR (
  22.                                                         ni.workActivityID = 'three_approve_2'
  23.                                                         AND ni.nextOperation = '4'
  24.                                                  )
  25.                                           )
  26.                                           OR ce. STATUS IN (
  27.                                                  '251',
  28.                                                  '252',
  29.                                                  '253',
  30.                                                  '254',
  31.                                                  '255',
  32.                                                  '219B'
  33.                                           )
  34.                                    )
  35.                             AND ni.nodeCode LIKE 'XS-%'
  36.                             GROUP BY
  37.                                    ni.nodeCode

                               

2.2 在该临时表的nodeCode上创建一个索引

CREATE INDEX ind_tmp_nodeCode   ON baidd_test_20200803(nodeCode);

2.3 改写sql

将所有以下sql:

  1. (
  2.                                    SELECT
  3.                                             ni.nodeCode,
  4.                                    IF (
  5.                                           ni.workActivityID IS NULL,
  6.                                           ce.statusDate,
  7.                                           ni.opreateDate
  8.                                    ) AS 'statusDate'
  9.                                    FROM
  10.                                           nodeInfo ni
  11.                                    LEFT JOIN clue ce ON ni.nodeCode = ce.serialNum
  12.                                    WHERE
  13.                                           (
  14.                                                  ni.workActivityID = 'finish_clue'
  15.                                                  AND ni.nextOperation = '00'
  16.                                                  OR (
  17.                                                         (
  18.                                                                ni.workActivityID = 'four_approve_2'
  19.                                                                AND ni.nextOperation = '4'
  20.                                                         )
  21.                                                         OR (
  22.                                                                ni.workActivityID = 'three_approve_2'
  23.                                                                AND ni.nextOperation = '4'
  24.                                                         )
  25.                                                  )
  26.                                                  OR ce. STATUS IN (
  27.                                                         '251',
  28.                                                         '252',
  29.                                                         '253',
  30.                                                         '254',
  31.                                                         '255',
  32.                                                         '219B'
  33.                                                  )
  34.                                           )
  35.                                    AND ni.nodeCode LIKE 'XS-%'
  36.                                    GROUP BY ni.nodeCode
  37.                             )

替换为baidd_test_20200803

2.4 示例

修改前的sql: 

  1. SELECT
  2.                                    ce.orgCode,
  3.                                    ce.serialNum
  4.                             FROM
  5.                                    clue ce
  6.                             LEFT JOIN clue pce ON pce.serialNum = ce.parentId
  7.                             LEFT JOIN (
  8.                                    SELECT
  9.                                             ni.nodeCode,
  10.                                    IF (
  11.                                           ni.workActivityID IS NULL,
  12.                                           ce.statusDate,
  13.                                           ni.opreateDate
  14.                                    ) AS 'statusDate'
  15.                                    FROM
  16.                                           nodeInfo ni
  17.                                    LEFT JOIN clue ce ON ni.nodeCode = ce.serialNum
  18.                                    WHERE
  19.                                           (
  20.                                                  ni.workActivityID = 'finish_clue'
  21.                                                  AND ni.nextOperation = '00'
  22.                                                  OR (
  23.                                                         (
  24.                                                                ni.workActivityID = 'four_approve_2'
  25.                                                                AND ni.nextOperation = '4'
  26.                                                         )
  27.                                                         OR (
  28.                                                                ni.workActivityID = 'three_approve_2'
  29.                                                                AND ni.nextOperation = '4'
  30.                                                         )
  31.                                                  )
  32.                                                  OR ce. STATUS IN (
  33.                                                         '251',
  34.                                                         '252',
  35.                                                         '253',
  36.                                                         '254',
  37.                                                         '255',
  38.                                                         '219B'
  39.                                                  )
  40.                                           )
  41.                                    AND ni.nodeCode LIKE 'XS-%'
  42.                                    GROUP BY ni.nodeCode
  43.                             ) cezt ON cezt.nodeCode = ce.serialNum
  44.                            

修改后的sql:

  1. SELECT
  2.                                    ce.orgCode,
  3.                                    ce.serialNum
  4.                             FROM
  5.                                    clue ce
  6.                             LEFT JOIN clue pce ON pce.serialNum = ce.parentId
  7.                             LEFT JOIN baidd_test_20200803 cezt ON cezt.nodeCode = ce.serialNum

查询结果由1.8秒降为0.02秒。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/871399
推荐阅读
相关标签
  

闽ICP备14008679号