Для следующей схемы и примера данных
CREATE TABLE T
(
A INT NULL,
B INT NOT NULL IDENTITY,
C CHAR(8000) NULL,
UNIQUE CLUSTERED (A, B)
)
INSERT INTO T
(A)
SELECT NULLIF(( ( ROW_NUMBER() OVER (ORDER BY @@SPID) - 1 ) / 1003 ), 0)
FROM master..spt_values
Приложение обрабатывает строки из этой таблицы в порядке кластерного индекса в 1000 фрагментов строки.
Первые 1000 строк извлекаются из следующего запроса.
SELECT TOP 1000 *
FROM T
ORDER BY A, B
Последний ряд этого набора ниже
+------+------+
| A | B |
+------+------+
| NULL | 1000 |
+------+------+
Есть ли способ написать запрос, который просто просматривает этот составной индексный ключ и затем следует за ним, чтобы получить следующий кусок из 1000 строк?
/*Pseudo Syntax*/
SELECT TOP 1000 *
FROM T
WHERE (A, B) is_ordered_after (@A, @B)
ORDER BY A, B
Наименьшее количество операций чтения, которые мне удалось получить, - 1020, но запрос кажется слишком запутанным. Есть ли более простой способ равной или лучшей эффективности? Возможно, тот, которому удается сделать все это в одном диапазоне поиска?
DECLARE @A INT = NULL, @B INT = 1000
;WITH UnProcessed
AS (SELECT *
FROM T
WHERE ( EXISTS(SELECT A
INTERSECT
SELECT @A)
AND B > @B )
UNION ALL
SELECT *
FROM T
WHERE @A IS NULL AND A IS NOT NULL
UNION ALL
SELECT *
FROM T
WHERE A > @A
)
SELECT TOP 1000 *
FROM UnProcessed
ORDER BY A,
B
FWIW: Если столбец A
выполнен NOT NULL
и значение страж -1
используются вместо эквивалентного план выполнения , безусловно , выглядит проще
Но один оператор поиска в плане по- прежнему выполняет два поиска, а не сворачивает их в один непрерывный диапазон, и логические операции чтения практически одинаковы, поэтому я подозреваю, что, возможно, это почти так же хорошо, как получится?
источник
NULL
ценности всегда на первом месте. (предполагается обратное.) Исправленное состояние в Fiddle(NULL, 1000 )
@A
равно ли оно нулю или нет, кажется, что оно не выполняет сканирование. Но я не могу понять, лучше ли планы, чем ваш запрос. Скрипка-2Ответы:
Моё любимое решение - использовать
API
курсор:Общая стратегия - это одно сканирование, которое запоминает свою позицию между вызовами. Использование
API
курсора означает, что мы можем возвращать блок строк, а не по одной за раз, как в случае сT-SQL
курсором:STATISTICS IO
Выход:источник