3

我有一个相当长的查询(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,次要是 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)
4

2 回答 2

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 。您可以在每个中看到执行计划。

祝你好运。

于 2013-01-19T01:41:30.917 回答
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
于 2013-01-19T01:24:56.183 回答