Внутренние проблемы с производительностью курсор


Пока я пытался избежать с помощью курсора из-за проблем с производительностью. Но теперь мне нужно сделать некоторые расчеты, чтобы достичь какой-то цели. У меня есть хранимая процедура, которая имеет такой код:

DECLARE  Outer_Cursor CURSOR FOR...

   OPEN Outer_Cursor
   FETCH NEXT FROM Outer_Cursor INTO ...

   WHILE @@FETCH_STATUS = 0
   BEGIN

      DECLARE  Inner_Cursor CURSOR  FOR...

      OPEN Inner_Cursor
      FETCH NEXT FROM Inner_Cursor INTO ...

      WHILE @@FETCH_STATUS = 0
      BEGIN

        ...

        FETCH NEXT FROM Inner_Cursor INTO ...
      END

      CLOSE Inner_Cursor
      DEALLOCATE Inner_Cursor    

      FETCH NEXT FROM Outer_Cursor INTO ...

  END

  CLOSE Outer_Cursor
  DEALLOCATE Outer_Cursor

Можно ли избежать (минимизировать) такие дорогие курсора отдыха внутренний курсор. Как я могу повторно использовать внутренний объявлении курсора, если это возможно?



277
4
задан 16 мая 2011 в 02:05 Источник Поделиться
Комментарии
2 ответа

Рекомендуется, чтобы покончить с курсорами. Оба из них. Всегда есть более эффективные решения.

Если это возможно, свести проблему к одному, что может быть решена с помощью наборов вместо итерации.

Но, если эта вложенная итерация невозможно избежать, вы все равно получите гораздо лучшую производительность, используя табличные переменные и, А вместо петель курсора. Например:

DECLARE @outerData TABLE (outerID INT, outerColumn VARCHAR(50), PRIMARY KEY (outerID))
DECLARE @innerData TABLE (innerID INT, innerColumn VARCHAR(50), PRIMARY KEY (innerID))
DECLARE @currOuter INT
DECLARE @currInner INT

INSERT INTO @outerData
SELECT EmployeeID, EmployeeName
FROM dbo.Employee

WHILE EXISTS (SELECT outerID FROM @outerData)
BEGIN
SELECT @currOuter = TOP outerID FROM @outerData

INSERT INTO @innerData
SELECT SaleID, SaleDesc
FROM EmployeeSales
WHERE EmployeeID = @outerID

WHILE EXISTS (SELECT innerID FROM @innerData)
BEGIN
SELECT @currInner = TOP innerID FROM @innerData

--Do work with inner data

...blah-de-blah...

--Delete after work is finished
DELETE FROM @innerData WHERE innerID = @currInner
END

--Delete current outerID and empty the innerdata table
--to prepare to move to the next record

DELETE FROM @outerData WHERE outerID = @currOuter
DELETE FROM @innerData
END

5
ответ дан 15 декабря 2011 в 05:12 Источник Поделиться

Если внутренний курсор можно запускать через один раз, создать табличную переменную и хранить результаты там, чтобы быть повторно использованы перед началом работы в наружной курсор.

И насколько расчеты идут, можно ли покончить с курсорами с помощью обобщенных табличных выражений?

2
ответ дан 13 августа 2011 в 04:08 Источник Поделиться