游标循环中的TSQL速度更快

游标循环中的TSQL速度更快,tsql,cursor,Tsql,Cursor,建立一个查询 单个查询如下所示,运行时间为7.0秒。它确实返回了正确的答案。需要根据特定条件对行进行计数,然后获得最大计数。我的问题是这个备用查询的性能。用游标包装的同一个查询需要0.15秒。在游标中,查询计划大不相同。如何使独立查询运行得更快 使用提示可以使单机版计划看起来像光标计划,从而解决了速度问题 固定查询:(由于选项失败,并非始终固定) 问题查询: select getdate(); go select max(list.match) as 'max' from (

建立一个查询

单个查询如下所示,运行时间为7.0秒。它确实返回了正确的答案。需要根据特定条件对行进行计数,然后获得最大计数。我的问题是这个备用查询的性能。用游标包装的同一个查询需要0.15秒。在游标中,查询计划大不相同。如何使独立查询运行得更快


使用提示可以使单机版计划看起来像光标计划,从而解决了速度问题

固定查询:(由于选项失败,并非始终固定)

问题查询:

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;