Skip to content

Об оценке строк табличной переменной

Пересказ статьи Gail Shaw. On table variable row estimations


На первый взгляд, вопрос об оценке количества строк табличной переменной кажется легким.


Но действительно ли это так просто? Ну, нет. Чтобы вникнуть почему, сначала нам нужно выяснить, отчего табличные переменные оцениваются одной строкой. Ответ очевидный - потому что они не имеют статистики. Однако...

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)

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.