[英]Improving query performance - DB2 SQL
我是 SQL 的新手,我正在尝试在 DB2 中编写查询。 但我认为它的效率相当低,因为它需要更多的资源。 如果有人可以提供任何可以使以下查询更有效的建议,我将不胜感激。 我知道需要了解实际需求/系统知识才能提供更好的建议,但乍一看,如果你们认为有些事情搞砸了,请告诉我。 提前致谢。
干杯,DK。
SELECT LIF.EMPID, LIF.BPA_NR , YEAR(LIF.BEG_DTE) ,MONTH(LIF.BEG_DTE) ,LIF.TFIDZ
, LVA.TRFIDZ, UZA.TRFIDZ, YEAR(LIF.BEG_DTE) - YEAR(KAR.DOB)
, ((YEAR(APK.TERMDT) - YEAR(APK.BEGDAT)) * 12 + MONTH(APK.TERMDT) - MONTH(APK.BEGDAT))
, KAR.DTHSUM, LVA.LVAGELD, UZA.UZAGELD, APK.EMIRKA
, LVA.EMILVA, UZA.EMIUZA , APK.EPROM, LVA.EPROM, UZA.EPROM
, LIF.LOANNR ,LIF.SUMAMT , MONTH(JOU.ZDATE), YEAR(JOU.ZDATE)
, (YEAR(JOU.ZDATE) - YEAR(APK.BEGDAT))*12 + MONTH(JOU.ZDATE) - MONTH(APK.BEGDAT)
, COALESCE(JOU.TYP,'OTH') , COALESCE(PRO1.BOOKEMI,0)
, COALESCE(PRO2.BOOKEMI,0),COALESCE(PRO3.BOOKEMI,0)
FROM DEVDBA.LIFE LIF
LEFT OUTER JOIN (
SELECT ( CASE WHEN JU6.REASN = 'AAA'
AND NOT EXISTS (
SELECT 1 FROM DEVDBA.LOGTBL JU7
WHERE JU7.EMPID=JU6.EMPID
AND JU7.GANID>JU6.GANID
AND JU7.ZDATE=JU6.ZDATE
AND JU7.REASN='BBB'
) THEN 'KRE'
WHEN JU6.REASN IN ('EEE','DDD')
THEN 'SON'
ELSE 'OTH'
END) AS TYP
, JU6.EMPID, JU6.REASN, JU6.ZDATE, JU6.GANID
FROM DEVDBA.LOGTBL JU6
WHERE JU6.REASN IN ('AAA','EEE','DDD')
) JOU
ON LIF.EMPID = JOU.EMPID
AND LIF.ZUNID = JOU.GANID
LEFT OUTER JOIN DEVDBA.LVAGR LVA
ON JOU.EMPID = LVA.EMPID
AND JOU.GANID = LVA.ZUNID
LEFT OUTER JOIN DEVDBA.UZAGR UZA
ON JOU.EMPID = UZA.EMPID
AND JOU.GANID = UZA.ZUNID
LEFT OUTER JOIN DEVDBA.APKGR APK
ON JOU.EMPID = APK.EMPID
AND JOU.GANID = APK.ZUNID
LEFT OUTER JOIN DEVDBA.KARGR KAR
ON JOU.EMPID = KAR.EMPID
AND JOU.GANID = KAR.ZUNID
LEFT OUTER JOIN (
SELECT PR1.EMPID, PR1.GANID, PR1.BOOKEMI
FROM DEVDBA.COMMS PR1, DEVDBA.LOGTBL JU1
WHERE PR1.PROVART IN ('789')
AND PR1.EMPID = JU1.EMPID
AND PR1.GANID = JU1.GANID
) PRO1
ON JOU.EMPID = PRO1.EMPID
AND JOU.GANID = PRO1.GANID
LEFT OUTER JOIN (
SELECT PR3.EMPID, PR3.GANID, PR3.BOOKEMI
FROM DEVDBA.COMMS PR3, DEVDBA.LOGTBL JU3
WHERE PR3.PROVART IN ('123')
AND PR3.EMPID = JU3.EMPID
AND PR3.GANID = JU3.GANID
) PRO2
ON JOU.EMPID = PRO2.EMPID
AND JOU.GANID = PRO2.GANID
LEFT OUTER JOIN (
SELECT PR5.EMPID, PR5.GANID, PR5.BOOKEMI
FROM DEVDBA.COMMS PR5, DEVDBA.LOGTBL JU5
WHERE PR5.PROVART IN ('456')
AND PR5.EMPID = JU5.EMPID
AND PR5.GANID = JU5.GANID
) PRO3
ON JOU.EMPID = PRO3.EMPID
AND JOU.GANID = PRO3.GANID
WHERE LIF.BPA_NR IN ('001','002')
AND JOU.TYP <> 'OTH'
AND LIF.BEG_DTE BETWEEN '01.01.2022' AND '31.12.2099'
ORDER BY LIF.BPA_NR,LIF.EMPID WITH UR;
本身不是一个答案,但很想发表评论,所以无论如何我都会在这里添加它。
不知道更多细节很难说太多。 您应该首先查看访问计划。 我发现db2caem非常好,因为它为每个运算符输出估计的基数和实际的基数。 如果操作员有很大差异,通常会提示从哪里开始调查。
db2advis kan 会为您提供一些有关缺失索引的提示,但不要认为它是理所当然的,它通常会建议冗余索引,因此您必须调查它推荐的内容。 如果您无权访问 db2advis,您可能想尝试:
它是一个 python 脚本,它生成与 db2advis 相同的索引候选集,然后评估索引组合的幂集及其估计改进,并选择最佳的 1-index、2-index、...、n-index 组合。 幂集的基数增长很快,因此可以为要研究的索引组合设置下限和上限。 使用风险自负
关于代码本身的一些观察。 过去,当混合“逗号”连接和 ansi 连接时,我在优化器中看到了一些神秘的效果。 我建议您替换以下结构:
LEFT OUTER JOIN (
SELECT PR1.EMPID, PR1.GANID, PR1.BOOKEMI
FROM DEVDBA.COMMS PR1, DEVDBA.LOGTBL JU1
WHERE PR1.PROVART IN ('789')
AND PR1.EMPID = JU1.EMPID
AND PR1.GANID = JU1.GANID
) PRO1
和:
LEFT OUTER JOIN (
SELECT PR1.EMPID, PR1.GANID, PR1.BOOKEMI
FROM DEVDBA.COMMS PR1
JOIN DEVDBA.LOGTBL JU1
ON PR1.EMPID = JU1.EMPID
AND PR1.GANID = JU1.GANID
WHERE PR1.PROVART IN ('789')
) PRO1
您似乎在 PRO1、PRO2 和 PRO3 中重复相同的连接:
LEFT OUTER JOIN (
SELECT PR1.EMPID, PR1.GANID, PR1.BOOKEMI
FROM DEVDBA.COMMS PR1, DEVDBA.LOGTBL JU1
WHERE PR1.PROVART IN ('789')
AND PR1.EMPID = JU1.EMPID
AND PR1.GANID = JU1.GANID
) PRO1
ON JOU.EMPID = PRO1.EMPID
AND JOU.GANID = PRO1.GANID
LEFT OUTER JOIN (
SELECT PR3.EMPID, PR3.GANID, PR3.BOOKEMI
FROM DEVDBA.COMMS PR3, DEVDBA.LOGTBL JU3
WHERE PR3.PROVART IN ('123')
AND PR3.EMPID = JU3.EMPID
AND PR3.GANID = JU3.GANID
) PRO2
ON JOU.EMPID = PRO2.EMPID
AND JOU.GANID = PRO2.GANID
...
您可能想调查是否可以改写为:
LEFT OUTER JOIN (
SELECT PR1.EMPID, PR1.GANID, PR1.BOOKEMI, PR1.PROVART
FROM DEVDBA.COMMS PR1
JOIN DEVDBA.LOGTBL JU1
ON PR1.EMPID = JU1.EMPID
AND PR1.GANID = JU1.GANID
WHERE PR1.PROVART IN ('789', '123', '456')
) PRO
ON JOU.EMPID = PRO.EMPID
AND JOU.GANID = PRO.GANID
然后在您的 select 中对 PROVART 使用 case 表达式来跟踪结果的来源
有时,它还可以帮助使用 LATERAL 手动将连接谓词推送到派生表中
LEFT OUTER JOIN LATERAL (
SELECT PR1.EMPID, PR1.GANID, PR1.BOOKEMI, PR1.PROVART
FROM DEVDBA.COMMS PR1
JOIN DEVDBA.LOGTBL JU1
ON PR1.EMPID = JU1.EMPID
AND PR1.GANID = JU1.GANID
WHERE PR1.PROVART IN ('789', '123', '456')
AND JOU.EMPID = PR1.EMPID
AND JOU.GANID = PR1.GANID
) PRO
ON JOU.EMPID = PRO.EMPID
AND JOU.GANID = PRO.GANID
只是一些想法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.