加入小表时查询减速

时间:2013-07-25 17:09:00

标签: sql-server performance

我遇到了一个奇怪的问题。我有一个使用4个表的查询(抱歉拉脱维亚名称):

  • KL_PrecesIzejvielas:20行
  • Parvietots_details:27897行
  • Razots:282行
  • KL_Simple:25行

表只有聚集索引(主键),没有其他索引。

我正在执行查询:

SELECT  KL_PrecesIzejvielas.APRAKSTS AS PreceNosauk ,
        COUNT(*) AS RazosanuSkaits ,
        SUM(SKAITS) AS Kopskaits ,
        Mervienibas.APRAKSTS AS Mervieniba
FROM    KL_Simple AS Mervienibas
        INNER JOIN ( KL_PrecesIzejvielas
                     INNER JOIN ( Parvietots_details
                                  INNER JOIN Razots ON Parvietots_details.ID_PARVIETOTS_MASTER = Razots.ID_PRECES_IEKS_KUST_ID
                                ) ON KL_PrecesIzejvielas.ID = Parvietots_details.ID_PRECE_IZEJVIELA
                   ) ON Mervienibas.ID = KL_PrecesIzejvielas.DEFAULT_MERVIENIBA
WHERE   Razots.ID_ATBILDPERSONA = 27
        AND Razots.DATUMSLAIKS >= ( SELECT TOP 1
                                            DATUMS
                                    FROM    LoginHistory
                                    WHERE   ID_USER = 27
                                    ORDER BY DATUMS DESC
                                  )
GROUP BY KL_PrecesIzejvielas.APRAKSTS ,
        Mervienibas.APRAKSTS
ORDER BY KL_PrecesIzejvielas.APRAKSTS ,
        Mervienibas.APRAKSTS

这是执行计划: exec plan Link to bigger picture

查询需要6秒钟才能处理!执行计划表明,在将大型Parvietots_details表连接到KL_PrecesIzejvielas时,最大的工作是完成的,并且在“Razots”上应用过滤器之前完成。这似乎不对。

奇怪的是,如果我只带走25行的小表KL_Simple / Mervienibas现在的执行时间只有126毫秒。现在,在“Razots”上应用过滤器后,大桌子就加入了,我认为这就是它的不同之处(?)

SELECT  KL_PrecesIzejvielas.APRAKSTS AS PreceNosauk ,
        COUNT(*) AS RazosanuSkaits ,
        SUM(SKAITS) AS Kopskaits
FROM    KL_PrecesIzejvielas
        INNER JOIN ( Parvietots_details
                     INNER JOIN Razots ON Parvietots_details.ID_PARVIETOTS_MASTER = Razots.ID_PRECES_IEKS_KUST_ID
                   ) ON KL_PrecesIzejvielas.ID = Parvietots_details.ID_PRECE_IZEJVIELA
WHERE   Razots.ID_ATBILDPERSONA = 27
        AND Razots.DATUMSLAIKS >= ( SELECT TOP 1
                                            DATUMS
                                    FROM    LoginHistory
                                    WHERE   ID_USER = 27
                                    ORDER BY DATUMS DESC
                                  )
GROUP BY KL_PrecesIzejvielas.APRAKSTS
ORDER BY KL_PrecesIzejvielas.APRAKSTS

exec plan Link to bigger picture

减速的原因是什么?我应该重写我的查询吗?为什么查询处理器会选择这样的计划?

我也尝试删除统计信息,但没有任何改进。

编辑: 以下是执行计划XML:
slow query
fast query

2 个答案:

答案 0 :(得分:0)

由于尺寸/语言,很难阅读截图/ SQL。它看起来好像是你将JOIN结构化为KL_Simple意味着对KL_Simple中的每一行都重复了其余的查询。

答案 1 :(得分:0)

我认为 where 子句和内部联接的执行顺序不会对查询性能产生任何影响。

第二个查询表现更好的唯一原因是您已从联接列表中删除了其他表。您仍然可以通过执行以下查询来确认事实。在这里,我将查询与CTE中的where子句分开,然后在join中使用它。

with Razots_CTE(ID_ATBILDPERSONA,DATUMSLAIKS,ID_PRECES_IEKS_KUST_ID)as
(select ID_ATBILDPERSONA,DATUMSLAIKS,ID_PRECES_IEKS_KUST_ID from Razots WHERE Razots.ID_ATBILDPERSONA=27 
AND Razots.DATUMSLAIKS >= (SELECT TOP 1 DATUMS FROM LoginHistory WHERE ID_USER=27 ) )

SELECT KL_PrecesIzejvielas.APRAKSTS AS PreceNosauk, 
Count(*) AS RazosanuSkaits, 
SUM(SKAITS) AS Kopskaits
FROM KL_PrecesIzejvielas INNER JOIN 
(Parvietots_details INNER JOIN 
Razots_CTE Razots
ON Parvietots_details.ID_PARVIETOTS_MASTER=Razots.ID_PRECES_IEKS_KUST_ID) 
ON KL_PrecesIzejvielas.ID=Parvietots_details.ID_PRECE_IZEJVIELA
GROUP BY KL_PrecesIzejvielas.APRAKSTS
ORDER BY KL_PrecesIzejvielas.APRAKSTS