我遇到了一个奇怪的问题。我有一个使用4个表的查询(抱歉拉脱维亚名称):
表只有聚集索引(主键),没有其他索引。
我正在执行查询:
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
这是执行计划: 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
减速的原因是什么?我应该重写我的查询吗?为什么查询处理器会选择这样的计划?
我也尝试删除统计信息,但没有任何改进。
编辑:
以下是执行计划XML:
slow query
fast query
答案 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