【发布时间】:2012-07-23 19:43:45
【问题描述】:
构建查询。
单个查询如下所示,运行时间为 7.0 秒。它确实返回正确的答案。需要根据特定条件对行数进行计数,然后得到最大计数。我的问题是这种支持查询的性能。包裹在游标中的相同查询是 0.15 秒。在游标中,查询计划有很大不同。如何使独立查询运行得更快?
使用提示能够让独立计划看起来像光标计划,并解决了速度问题。
固定查询:(并非一直固定,因为 OPTION 失败)
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [docSVenum1] with (nolock)
INNER LOOP JOIN [FTSindexWordOnce] as w1 with (NOLOCK, FORCESEEK)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER HASH JOIN [FTSindexWordOnce] as w2 with (NOLOCK)
ON w1.wordID = w2.wordID and w2.[sID] = '2'
GROUP BY W1.[sID]
-- OPTION (HASH GROUP)
) as list;
问题查询:
select getdate();
go
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = '2'
GROUP BY W1.[sID]
) as list;
go
select getdate(); -- 7.0 seconds
我还需要针对多个值运行该单个查询并将其放入带有循环的游标中。我知道光标不好,但我不知道如何在没有光标的情况下做到这一点。
独立的查询和循环内都返回相同的正确答案。
令我惊讶的是,游标循环中完全相同的查询快了 40 倍。
DECLARE @sid int
DECLARE sID_cursor CURSOR FOR
SELECT top 80 sID
FROM docSVsys
WHERE sID = '2' -- actually I want to not have this and let it loop through all
-- when i built the loop i saw performance improvement
ORDER BY sID
OPEN sID_cursor
FETCH NEXT FROM sID_cursor
INTO @sID
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @sID
select max(list.match) as 'max'
from
(
SELECT
count(*) as 'match'
FROM [FTSindexWordOnce] as w1 with (nolock)
INNER JOIN [docSVenum1] with (nolock)
ON [docSVenum1].sID = w1.[sID] and [docSVenum1].[enumID] = '142'
INNER JOIN [FTSindexWordOnce] as w2 with (nolock)
ON w1.wordID = w2.wordID AND w2.[sID] = @sID
GROUP BY W1.[sID]
) as list
FETCH NEXT FROM sID_cursor
INTO @sID
END
CLOSE sID_cursor;
DEALLOCATE sID_cursor;
go
select getdate(); -- 0.15 seconds
【问题讨论】:
-
避免使用光标。还有其他基于设置的选项。如果您解释 what 查询试图达到的目的,也许可以给出替代方案。
-
我不太明白你想要什么,因为你目前正在执行 80 个不同的
SELECTs。您的预期结果是什么? -
@Oded 是的,一般的智慧是避免光标。但在这种情况下,光标运行得更快。将添加更多解释。
-
@Lamak 是的,这是想要的结果
-
您没有回答@Lamak 的问题。你解释了你在在做什么,而不是为什么你在这样做(例如,想要的最终结果是什么)。