我有一个相当长的(10个表,每个约60k记录)查询,所有这些表都使用左连接连接,因为它们可以包含空值(所有这些)。
我看到了巨大的性能损失,我将其跟踪到这段代码。
SELECT *
FROM MAIN_TABLE d
LEFT JOIN INSURANCES i on i.IMREDEM_CODE = d.IMREDEM_CODE
and i.INS_TERMINATIONDATE IS NULL
and INS_RANK = 0
and i.IMREINS_CODE = (SELECT TOP 1 IMREINS_CODE
from INSURANCES i2
WHERE i2.IMREDEM_CODE = i.IMREDEM_CODE
and i2.INS_TERMINATIONDATE IS NULL
and i2.INS_RANK = 0
ORDER BY TAG_SYSTEMDATE DESC)
基本上我需要做的是保险表可能包含0个或多个记录,因为当他们更新保险时,它会执行插入而不是更新以用于审计目的。所以我必须在左边的连接上加入桌子两次。此外,我需要为主要和次要保险两次执行此查询(主要是rank = 0,secondary是rank = 1.IMREDEM_CODE是D表的PK和i表的FK。
答案就在这里:
left join INSURANCES i on i.IMREDEM_CODE = d.IMREDEM_CODE
and i.IMREINS_CODE = (SELECT max(imreins_code) FROM INSURANCES i2 WHERE i2.IMREDEM_CODE = i.IMREDEM_CODE and i2.INS_TERMINATIONDATE IS NULL and i2.INS_RANK = 0)
答案 0 :(得分:2)
虽然我确信你可以进一步优化这一点,但我已经快速尝试了。您的执行计划将执行3次表扫描。您可以尝试将其减少到2:
SELECT *
FROM Main_Table d
LEFT JOIN
(SELECT TOP 1 *
FROM Insurances
WHERE INS_TERMINATIONDATE IS NULL
AND INS_RANK = 0
ORDER BY TAG_SYSTEMDATE DESC) i on i.IMREDEM_CODE = d.IMREDEM_CODE;
可能有比TOP 1和Order By更好的方法,但是我已经厌倦了,现在想不到它。无论哪种方式,这肯定更有效。
以下是包含两组查询的SQL Fiddle。您可以在每个中看到执行计划。
祝你好运。答案 1 :(得分:1)
我相信以下内容会给你完全相同但更快的结果;
SELECT *
FROM MAIN_TABLE d
LEFT JOIN INSURANCES i on i.IMREDEM_CODE = d.IMREDEM_CODE
and i.IMREINS_CODE = select max(i.imreins_code) from INSURANCES
and i.INS_TERMINATIONDATE IS NULL
and i.INS_RANK = 0