Как прокомментировано, я бы использовал здесь таблицу подсчета, а не rCTE:
DECLARE @Start int, @End int;
SET @Start = 100000;
SET @End = 200000;
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) I
FROM N N1, N N2, N N3, N N4, N N5, N N6) --1M rows should be enough
SELECT T.I AS MISSING_INVOICE_NO
FROM Tally T
--LEFT JOIN YourTable YT ON T.I = YT.INVOICE_NO
WHERE T.I BETWEEN @Start AND @End
--AND YT.INVOICE_NO IS NULL
Вам нужно закомментировать и настроить строки на JOIN
для вашей таблицы.
В качестве доказательства рассуждений используйте следующие сценарии:
DECLARE @Start int, @End int;
SET @Start = 100000;
SET @End = 200000;
SET STATISTICS TIME ON;
PRINT N'Tally Table';
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) I
FROM N N1, N N2, N N3, N N4, N N5, N N6) --1M rows should be enough
SELECT *
FROM Tally T
WHERE T.I BETWEEN @Start AND @End;
PRINT N'rCTe';
WITH rCTE AS(
SELECT @Start AS I
UNION ALL
SELECT I + 1
FROM rCTE r
WHERE r.I + 1 <= @End)
SELECT *
FROM rCTE
OPTION (MAXRECURSION 0);
SET STATISTICS TIME OFF;
Время, необходимое для заполнения таблицы подсчета (в моем экземпляре Production):
CPU time = 78 ms, elapsed time = 106 ms.
CPU time = 78 ms, elapsed time = 95 ms.
CPU time = 62 ms, elapsed time = 91 ms.
CPU time = 78 ms, elapsed time = 105 ms.
Метод rCTE, однако, был таким:
CPU time = 2547 ms, elapsed time = 3695 ms.
CPU time = 2250 ms, elapsed time = 2500 ms.
CPU time = 1813 ms, elapsed time = 1930 ms.
CPU time = 2750 ms, elapsed time = 3220 ms.
Это большая разница во времени, так как решение по подсчету составляло в среднем около 100 мс,где значение rCTe составляло от 2 до 4 секунд.