TSQL在光标循环中更快

时间:2012-07-23 19:43:45

标签: tsql cursor

建立查询。

单个查询如下所示,并在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

1 个答案:

答案 0 :(得分:1)

使用提示能够独立计划看起来像光标计划并修复了速度问题。

修正查询:(并非一直修复为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;