SQL Server не имеет статистики для переменной таблицы?

Я обнаружил, что MSDN говорит, что "у табличных переменных нет статистики"

https://msdn.microsoft.com/en-us/library/dd535534(v=sql.100).aspx

Также в следующей статье говорится, что SQL Server не поддерживает статистику для табличной переменной даже в SQL 2014

"временные таблицы легко превосходят переменные таблиц, потому что их способность получать статистику значительно улучшает оптимизацию запросов. Это остается верным с улучшениями в SQL Server 2014".

https://www.brentozar.com/archive/2014/04/table-variables-good-temp-tables-sql-2014/

Затем я провожу тестирование с SQL Server 2014 и нахожу статистику для табличной переменной, поэтому в SQL 2014 теперь у табличной переменной есть статистика, верно?

DECLARE
@tb_table TABLE(
RowID INT IDENTITY(1,1) NOT NULL PRIMARY KEY
,ProductName NVARCHAR(50) NOT NULL UNIQUE
,Indate DATETIME NOT NULL  DEFAULT(GETDATE())
,index IX_Indate NONCLUSTERED (Indate)
);

DECLARE
@table_variable_id bigint
;
SELECT TOP 1 @table_variable_id = object_id
FROM tempdb.sys.all_objects AS A
WHERE parent_object_id = 0
ORDER BY create_date DESC

SELECT  
statistics_name = st.name
,table_name = OBJECT_NAME(st.object_id)
,column_name = COL_NAME(stc.object_id, stc.column_id)
FROM    tempdb.sys.stats AS st WITH(NOLOCK) 
    INNER JOIN tempdb.sys.stats_columns AS stc WITH(NOLOCK)
        ON st.object_id = stc.object_id  
        AND st.stats_id = stc.stats_id 
 WHERE st.object_id = @table_variable_id

enter image description here

Кстати, если мы уберем строку "index IX_Indate NONCLUSTERED (Indate)" из приведенного выше сценария, мы все равно сможем увидеть две статистические записи в выходных данных на SQL-сервере, даже в SQL2012.

Ответ 1

В этой статье я нашел следующую фразу: Itzik Ben-Gan Улучшения в табличных переменных и временных таблицах в SQL Server 2014:

Оценки кардинальности с TF 2453

Последнее улучшение, о котором я расскажу в этой статье, касается таблицы переменные и доступны в SQL Server 2014 RTM CU3 и в SQL Сервер 2012 SP2. Здесь вы можете найти запись поддержки, описывающую ее здесь.

Хорошо известно, что SQL Server не поддерживает статистику как гистограммы и векторы плотности для переменных таблицы. Однако SQL Сервер сохраняет количество строк в таблице, что в некоторых случаях может значительно помочь в оптимизации оптимизатора.

Вы используете Enterprise Edition. Я думаю, это объясняет это. Статья Кендры Литтл говорит, что Enterprise Edition умнее.

Я попытаюсь проверить с помощью DBCC SHOW_STATISTICS информацию о найденных объектах статистики и подтвердить, есть ли у них все данные обычные объекты статистики. У объектов статистики, созданных для переменных таблицы, должно быть меньше данных, например, без гистограммы. Я не имею Enterprise Edition под рукой для тестирования.

Ответ 2

Нет SQL Server не поддерживает статистику для табличных переменных.

В вашем вопросе есть три индекса для табличной переменной, и SQL Server вставляет соответствующие три строки в sysidxstats

Содержит строку для каждого индекса или статистику для таблиц и индексированных представлений

Эти строки имеют установленный флаг 2 в столбце status указывающий, что они предназначены для статистики и поэтому возвращаются sys.stats но нет соответствующего объекта статистики.

Вы можете увидеть это с помощью запроса здесь (требуется подключение через ЦАП)

SELECT name,
       imageval
FROM   tempdb.sys.stats AS s
       INNER JOIN tempdb.sys.sysobjvalues AS o
               ON s.object_id = o.objid
                  AND s.stats_id = o.subobjid
WHERE  s.object_id = @table_variable_id; 

Который возвращается

+--------------------------------+----------+
|              name              | imageval |
+--------------------------------+----------+
| PK__#AD773B9__FFEE74513158C9C9 | NULL     |
| IX_Indate                      | NULL     |
| UQ__#AD773B9__DD5A978A62C2C478 | NULL     |
+--------------------------------+----------+

imageval который будет содержать фактическую статистику, равен NULL.

В этом нет ничего нового. Вы также видите то же самое в 2008 году (хотя только для PK и UQ, поскольку определение встроенного индекса не может быть использовано там).

Ведение подсчета строк выполняется отдельно и не требует полноценного объекта статистики с гистограммой. И снова это не ново.