Об оценке строк табличной переменной
Пересказ статьи Gail Shaw. On table variable row estimations
На первый взгляд, вопрос об оценке количества строк табличной переменной кажется легким.
Но действительно ли это так просто? Ну, нет. Чтобы вникнуть почему, сначала нам нужно выяснить, отчего табличные переменные оцениваются одной строкой. Ответ очевидный - потому что они не имеют статистики. Однако...
Эта таблица не имеет статистики, но, тем не менее, оценивает строки правильно.
Итак, это не только отсутствие статистики. Хммм... Какое еще есть отличие, связанное с табличной переменной?
Это связано с генерацией планов. Результатами расширенного события являются начало и конец оператора отслеживания событий и событие после компиляции для плана. Для запроса, использующего табличную переменную, весь пакет компилируется до начала выполнения. Для постоянной таблицы существует множество событий компиляции.
И это из-за того, что называется «отложенной компиляцией». Для табличной переменной весь пакет компилируется в начале, во время, когда табличная переменная не существует, и, поскольку статистики нет, перекомпиляция не включается после вставки данных. Следовательно, не может быть никакой другой оценки количества строк кроме 1, поскольку таблица не существовала, когда выполнялась оценка.
Для постоянной таблицы компиляция запроса, который использует таблицу откладывается до момента старта запроса, а не старта пакета. Следовательно, план запроса генерируется после того, как таблица уже создана и наполнена данными. Вот в чем разница.
Теперь по-прежнему нет статистики, и поэтому нет способа получить распределение данных, но это не единственный способ получить информацию о строках в таблице. Движок хранилища знает сколько строк в таблице, хотя распределение данных ему неизвестно.
Следовательно, для табличной переменной мы можем ожидать увидеть отличную от 1 оценку количества строк всякий раз, когда табличная переменная существует до компиляции запроса, который ее использует.
Это произойдет, когда табличная переменная является параметром табличного типа, когда запрос, использующий ее, имеет опцию RECOMPILE, и когда включена отложенная компиляция для табличных переменных в SQL 2019.
Табличнозначный параметр
Обычный select при уровне совместимости 140
Обычный select при уровне совместимости 150
select with OPTION(RECOMPILE)
ALTER DATABASE CURRENT SET AUTO_CREATE_STATISTICS OFF
GO
CREATE TABLE Test (SomeCol INT);
INSERT INTO Test (SomeCol)
VALUES (1),(22),(37),(45),(55),(67),(72),(86),(91)
SELECT SomeCol FROM Test
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID('Test')
DROP TABLE dbo.Test
Эта таблица не имеет статистики, но, тем не менее, оценивает строки правильно.
Итак, это не только отсутствие статистики. Хммм... Какое еще есть отличие, связанное с табличной переменной?
Это связано с генерацией планов. Результатами расширенного события являются начало и конец оператора отслеживания событий и событие после компиляции для плана. Для запроса, использующего табличную переменную, весь пакет компилируется до начала выполнения. Для постоянной таблицы существует множество событий компиляции.
И это из-за того, что называется «отложенной компиляцией». Для табличной переменной весь пакет компилируется в начале, во время, когда табличная переменная не существует, и, поскольку статистики нет, перекомпиляция не включается после вставки данных. Следовательно, не может быть никакой другой оценки количества строк кроме 1, поскольку таблица не существовала, когда выполнялась оценка.
Для постоянной таблицы компиляция запроса, который использует таблицу откладывается до момента старта запроса, а не старта пакета. Следовательно, план запроса генерируется после того, как таблица уже создана и наполнена данными. Вот в чем разница.
Теперь по-прежнему нет статистики, и поэтому нет способа получить распределение данных, но это не единственный способ получить информацию о строках в таблице. Движок хранилища знает сколько строк в таблице, хотя распределение данных ему неизвестно.
Следовательно, для табличной переменной мы можем ожидать увидеть отличную от 1 оценку количества строк всякий раз, когда табличная переменная существует до компиляции запроса, который ее использует.
Это произойдет, когда табличная переменная является параметром табличного типа, когда запрос, использующий ее, имеет опцию RECOMPILE, и когда включена отложенная компиляция для табличных переменных в SQL 2019.
CREATE OR ALTER PROCEDURE TestRowEstimations @Input TestTableType READONLY AS
SELECT SomeCol FROM @Input;
DECLARE @Test TABLE (SomeCol INT);
INSERT INTO @Test (SomeCol)
VALUES (1),(22),(37),(45),(55),(67),(72),(86),(91);
SELECT SomeCol FROM @Test;
SELECT SomeCol FROM @Test OPTION (RECOMPILE);
GO
Табличнозначный параметр
Обычный select при уровне совместимости 140
Обычный select при уровне совместимости 150
select with OPTION(RECOMPILE)
Обратные ссылки
Автор не разрешил комментировать эту запись
Комментарии
Показывать комментарии Как список | Древовидной структурой