Сначала я хотел бы отметить, что логика c в вашей вставке некорректна.
Когда @start начинается с 1, вы всегда пропускаете первую строку исходной таблицы. Затем добавление 1 к нему в конце вашего l oop приводит к тому, что он пропускает еще одну строку при каждом последующем запуске l oop.
. Если ваш набор использует пакетные вставки, я предлагаю вам прочитать о том, как это работает на MSSQLTips .
Чтобы помочь вам с производительностью, я бы посоветовал взглянуть на следующее:
SELECT *
Удалите SELECT *
и замените имена столбцов. Это поможет оптимизатору получить лучший план запросов. Дальнейшее чтение о том, почему SELECT *
плохо, можно найти в этом SO Вопросе .
ORDER BY
Что ORDER BY
, вероятно, замедляется ты вниз Не видя ваш план запроса, мы не можем знать наверняка. Каждый раз, когда ваш l oop выполняет, он запрашивает исходную таблицу и должен отсортировать все эти записи. Сортировать 20+ фрезерных записей, что много раз - много работы. Взгляните на мой упрощенный пример ниже.
CREATE TABLE #Test (Id INT);
INSERT INTO #Test VALUES (1), (2), (3), (4), (5);
DECLARE @batchsize INT;
DECLARE @start INT;
DECLARE @numberofrows INT;
SELECT @numberofrows = COUNT(*) FROM #Test;
SET @batchsize = 2;
SET @start = 0;
WHILE @start < @numberofrows
BEGIN
SELECT
*
, 10
FROM
#Test
ORDER BY
Id OFFSET @start ROWS FETCH NEXT @batchsize ROWS ONLY;
SET @start += @batchsize;
END;
Ниже приведена часть плана запроса, созданного образцом. Обратите внимание на операцию сортировки, выделенную желтым цветом. Его стоимость составляет 78% от этого плана запроса.
Если мы добавим индекс, который уже отсортирован в столбце Id исходной таблицы, мы можно устранить род. Теперь, когда запускается l oop, он не должен выполнять никакой сортировки.
CREATE INDEX ix_Test ON #Test (Id)
Другие варианты исследования
- Индексы Columnstore
- Пакетный режим в RowStore
- Параллельные вставки