stats_column_id и index_column_id не обновляются с изменением физического порядка кластеризованного индекса

14

Если я неправильно понимаю назначение столбца, следующий код указывает, что изменение структуры кластеризованного индекса не меняет порядковый номер ( stats_column_id) столбца в DMV sys.stats_columns . (Проверено в AdventureWorks2014, AdventureWorks2008R2)

select i.name, c.name, ic.column_id, ic.index_column_id
from sys.indexes i 
join sys.index_columns ic
    on i.object_id = ic.object_id
    and i.index_id = ic.index_id
join sys.columns c 
    on i.object_id = c.object_id
    and ic.column_id = c.column_id
where i.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by ic.key_ordinal;

select sh.name,s.name, c.name, c.column_id, sc.column_id, sc.stats_column_id
from sys.stats s 
join sys.stats_columns sc
    on s.object_id = sc.object_id
    and s.stats_id = sc.stats_id
join sys.columns c 
    on s.object_id = c.object_id
    and sc.column_id = c.column_id
join sys.tables t 
    on s.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
where s.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by sc.stats_column_id;

dbcc show_statistics('[Person].[BusinessEntityAddress]','PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID') with density_vector;

ALTER TABLE [Person].[BusinessEntityAddress] DROP CONSTRAINT [PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID]
GO

ALTER TABLE [Person].[BusinessEntityAddress] ADD  CONSTRAINT [PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID] PRIMARY KEY CLUSTERED 
(
    AddressID ASC,
    [BusinessEntityID] ASC, 
    [AddressTypeID] ASC
)
GO


select i.name, c.name, ic.column_id, ic.index_column_id
from sys.indexes i 
join sys.index_columns ic
    on i.object_id = ic.object_id
    and i.index_id = ic.index_id
join sys.columns c 
    on i.object_id = c.object_id
    and ic.column_id = c.column_id
where i.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by ic.key_ordinal;

select sh.name,s.name, c.name, c.column_id, sc.column_id, sc.stats_column_id
from sys.stats s 
join sys.stats_columns sc
    on s.object_id = sc.object_id
    and s.stats_id = sc.stats_id
join sys.columns c 
    on s.object_id = c.object_id
    and sc.column_id = c.column_id
join sys.tables t 
    on s.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
where s.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by sc.stats_column_id;

dbcc show_statistics('[Person].[BusinessEntityAddress]','PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID') with density_vector;

Однако векторы плотности указывают на изменение в главном столбце объекта индекса / статистики. Это фундаментальное недоразумение с моей стороны? Если так, то как мне найти ведущий столбец объекта статистики, используя DMV?

Протестированные версии SQL Server: 2008R2, 2014

swasheck
источник
1
Разве column_id - это порядковая позиция в таблице ? Что произойдет, если вы удалите и заново создадите таблицу и фактически измените порядковый номер этих столбцов? Сейчас у меня нет времени на тестирование, но я нахожу подозрительно удобным, что это 1,2,3 в статистике и 1,2,3 в таблице и sys.columns.
Аарон Бертран
@AaronBertrand да. а затем index_column_id - это ... что-то ... и key_ordinalэто порядок столбцов индекса (только что обнаружил). тем не менее, документация по sys.stats_columns указывает на то, что stats_column_id - это порядковая позиция, но я мог бы прочитать это совершенно неправильно.
swasheck
2
Я думаю, я мог бы просто использовать, INDEX_COL()хотя я смутно припоминаю, что кто-то
заметил,

Ответы:

1

По общему мнению, это может быть ошибочное поведение в DMV sys.stats_columns. Это, кажется, вызывает проблемы, когда статистика обновляется посредством родительского индекса. Я полагаю, что это связано с механизмом обновления статистики при изменении ограничения.

Если вы создаете статистику вручную, а затем хотите изменить столбцы, вы должны сначала удалить и заново создать, что заставляет метаданные обновляться в соответствующем DMV. В продемонстрированной вами операции возникает ситуация, когда метаданные не обновляются ни при каких обстоятельствах (DBCC *, CHECKPOINT, перезапуск сервера, обновление статистики посредством изменения родительского индекса и т. Д.) После внесения изменения. Из моего первоначального тестирования я могу найти только один случай, когда метаданные обновлены должным образом, это сценарий удаления и повторного создания.

Вы можете взглянуть на пункт «Подключиться» по данному вопросу и проголосовать в случае необходимости. Существует опубликованный там запрос для обхода, но его механизм основан на сопоставлении имени индекса со статистическим именем и использовании метаданных индекса.

Трэвис Пейдж
источник
1

У меня возникла та же проблема при попытке воспроизвести способ, которым другие получают информацию индекса из представлений sys.dm в SQL Server. Я просто не мог понять порядок столбцов в индексе.

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

SELECT s.name                  AS Schema_name,
       o.name                  AS Table_Name,
       i.type_desc             AS Index_Type,
       i.name                  AS Index_Name,
       c.name           AS Table_Column,
       i.fill_factor           AS Indx_Fill_Factor,
       ic.key_ordinal          AS [Key_ordinal (IDX Column_Order)],
       ic.index_column_id      AS Index_column_id,
       stc.stats_column_id     AS Stats_Col_ID,
       -- Additional info for each joined table
       -- comment out what you don't need
       -- 2 lines at a time
       --
       -- '| table object -->', -- column seperator
       -- o.*,
       -- '| schema object-->', -- column seperator
       -- s.*,
       '| index info-->', -- column seperator
       i.*,
       '| sys index info -->', -- column seperator
       si.*,
       '| indx cols info -->', -- column seperator
       ic.*,
       '| tab cols info -->', -- column seperator
       c.*,
       '| idx stats info -->', -- column seperator
       st.*,
       '| idx stats columns info -->', -- column seperator
       stc.*
FROM   sys.objects             AS o
       JOIN sys.schemas        AS s
            ON  s.schema_id = o.schema_id
       JOIN sys.indexes        AS i
            ON  i.object_id = o.object_id
       JOIN sys.sysindexes as si
            ON  si.[id] = i.object_id
            AND si.indid = i.index_id
       JOIN sys.index_columns  AS ic
            ON  ic.object_id = i.object_id
            AND ic.index_id = i.index_id
       JOIN sys.columns        AS c
            ON  c.object_id = ic.object_id
            AND c.column_id = ic.column_id
       JOIN sys.stats          AS st
            ON  st.object_id = i.object_id
            and st.stats_id = i.index_id 
      JOIN sys.stats_columns  AS stc
      ON c.column_id = stc.column_id
      AND stc.stats_id = st.stats_id
      AND stc.[object_id] = o.[object_id]
WHERE  1=1 
     --and i.type <> 1 -- Exclude Clustered Indexes. 0 = Heap; 1 = Clustered Index, 2 = Non-Clustered Index
       AND s.name != 'sys' -- Exclude sys items
       and o.name = 'BusinessEntityAddress'
       AND i.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
ORDER BY
       o.object_id,
       i.index_id,
       ic.key_ordinal

Столбец key_ordinalв таблице sys.index_columns - это порядок, в котором столбцы хранятся в индексе.

Там нет key_ordinalстолбца для sys.stats_columnsтаблицы. Столбец stats_column_idпросто копирует index_column_idстолбец объекта, на который он ссылается.

Существует небольшая разница в формулировке статьи sys.stats_columns (Transact-SQL) для столбца stats_column_id:

Порядковый номер на основе 1 в наборе столбцов статистики.

... и в статье sys.index_columns (Transact-SQL) для key_ordinalстолбца:

Порядковый номер (на основе 1) в наборе ключевых столбцов.

Я считаю, что index_column_id(sys.index_columns) и stats_column_id(sys.stats_columns) являются эквивалентными друг другу, и что только таблица sys.index_columns имеет столбец порядка, а именно key_ordinal.

Джон ака hot2use
источник