游标循环中的TSQL速度更快
建立一个查询 单个查询如下所示,运行时间为7.0秒。它确实返回了正确的答案。需要根据特定条件对行进行计数,然后获得最大计数。我的问题是这个备用查询的性能。用游标包装的同一个查询需要0.15秒。在游标中,查询计划大不相同。如何使独立查询运行得更快游标循环中的TSQL速度更快,tsql,cursor,Tsql,Cursor,建立一个查询 单个查询如下所示,运行时间为7.0秒。它确实返回了正确的答案。需要根据特定条件对行进行计数,然后获得最大计数。我的问题是这个备用查询的性能。用游标包装的同一个查询需要0.15秒。在游标中,查询计划大不相同。如何使独立查询运行得更快 使用提示可以使单机版计划看起来像光标计划,从而解决了速度问题 固定查询:(由于选项失败,并非始终固定) 问题查询: select getdate(); go select max(list.match) as 'max' from (
使用提示可以使单机版计划看起来像光标计划,从而解决了速度问题 固定查询:(由于选项失败,并非始终固定) 问题查询:
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
使用提示可以使单机版计划看起来像光标计划,从而解决了速度问题 固定查询:(由于选项失败,并非始终固定)
避免使用光标。还有其他基于设置的选项。如果你解释一下这个查询想要实现什么,也许可以给出一个替代方案。我不太明白你想要什么,因为你目前正在执行80个不同的
SELECT
s。你的预期结果是什么?@Oded是的,一般的智慧是避免光标。但在这种情况下,光标运行得更快。将添加更多解释。@Lamak是的,这是期望的结果您没有回答@Lamak的问题。你解释了你在做什么,而不是你为什么这么做(比如,你想要的最终结果是什么)。
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
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;