Во время экспериментов с выполнением общих запросов я заметил, что иногда в предполагаемом плане отображается просто «Запрос на выборку»
, а в фактическом плане - повторяющиеся выборки из сканирования кластеризованного индекса
на других случаи (например, при добавлении TOP
в запрос) t В оценочном плане показан этап «запроса заполнения», который заполняет рабочую таблицу
. Фактический план показывает сканирование кластерного индекса для заполнения рабочей таблицы с последующим повторным поиском по этой рабочей таблице.
(Дополнительный вопрос: если бы кто-нибудь мог объяснить, почему каждое сканирование в первом запросе считается за 2 логических чтения, это тоже может быть весьма поучительным)
Я нашел эту статью здесь , в которой объясняется, что Курсоры FAST_FORWARD
могут использовать динамический или статический план. Первый запрос в этом случае использует динамический план, а второй - статический.
Я также обнаружил, что если я попробую
SET @C2 = CURSOR DYNAMIC TYPE_WARNING FOR SELECT TOP ...
, курсор будет неявно преобразован в курсор набора ключей
, поэтому ясно, что конструкция TOP
не поддерживается для динамических курсоров. , возможно, по причинам в ответе Рубена - все еще ищу окончательное объяснение этого.
Однако я также читал, что динамические курсоры обычно медленнее , чем их статические аналоги ( источник 1 , источник 2 ), что кажется мне удивительным, учитывая что статическая разновидность должна читать исходные данные, копировать их, а затем читать копию, а не просто читать исходные данные. В статье, на которую я ссылался ранее , упоминается, что динамические курсоры используют маркеры
. Кто-нибудь может объяснить, что это такое? Это просто RID, ключ CI или что-то другое?
SET STATISTICS IO OFF
CREATE TABLE #T ( ord INT IDENTITY PRIMARY KEY, total INT, Filler char(8000))
INSERT INTO #T (total) VALUES (37),(80),(55),(31),(53)
DECLARE @running_total INT,
@ord INT,
@total INT
SET @running_total = 0
SET STATISTICS IO ON
DECLARE @C1 AS CURSOR;
SET @C1 = CURSOR FAST_FORWARD FOR SELECT ord, total FROM #T ORDER BY ord;
OPEN @C1;
PRINT 'Initial FETCH C1'
FETCH NEXT FROM @C1 INTO @ord, @total ;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @running_total = @running_total + @total
PRINT 'FETCH C1'
FETCH NEXT FROM @C1 INTO @ord, @total ;
END
SET @running_total = 0
SET STATISTICS IO ON
DECLARE @C2 AS CURSOR;
SET @C2 = CURSOR FAST_FORWARD FOR SELECT TOP 5 ord, total FROM #T ORDER BY ord;
OPEN @C2;
PRINT 'Initial FETCH C2'
FETCH NEXT FROM @C2 INTO @ord, @total ;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @running_total = @running_total + @total
PRINT 'FETCH C2'
FETCH NEXT FROM @C2 INTO @ord, @total ;
END
PRINT 'End C2'
DROP TABLE #T