stats_column_id та index_column_id не оновлюються, коли фізичний порядок кластерного індексу змінюється


14

Якщо я не розумію мету стовпця, наступний код вказує, що зміна структури кластерного індексу не змінює порядкового положення ( stats_column_id) стовпця в DMV sys.stats_column . (Випробувано в 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


1
Хіба стовпець_id не є порядковим положенням таблиці ? Що станеться, якщо ви скинете та знову створите таблицю і фактично зміните порядкове положення цих стовпців? Зараз у мене немає часу на тестування, але мені здається підозрілим зручним, що це 1,2,3 у статистиці та 1,2,3 у таблиці та колонках sys.column.
Аарон Бертран

@AaronBertrand так. а потім index_column_id - це ... щось ... і key_ordinalце порядок індексних стовпців (щойно виявив це). однак, здається, що документація на sys.stats_column вказує на те, що stats_column_id є порядковим положенням, але я можу читати це зовсім неправильно.
swasheck

2
Я думаю, я міг би просто використати, INDEX_COL()хоча я смутно згадую когось, зазначаючи, що ці функції помічників можуть бути не найкращою ідеєю
swasheck

Відповіді:


1

За всіма записами це може бути помилкова поведінка в DMV sys.stats_column. Це, мабуть, викликає проблеми, коли статистику оновлюють за допомогою батьківського індексу. Я вважаю, що це пов’язано з механізмом, за допомогою якого статистичні дані оновлюються в умовах обмеження.

Якщо ви створите статистику вручну, а потім хочете змінити стовпці, спершу потрібно скинути й заново створити, що змушує оновлювати метадані у відповідному 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_column - це порядок, в якому стовпці зберігаються в індексі.

У таблиці немає key_ordinalстовпця sys.stats_columns. Стовпчик stats_column_idпросто копіює index_column_idстовпчик об'єкта, на який він посилається.

Існує незначна різниця у формулюванні статті sys.stats_column (Transact-SQL) для стовпця stats_column_id:

Порядок на основі 1 в межах набору стовпців статистики.

... і в статті sys.index_column (Transact-SQL) для key_ordinalстовпця:

Звичайний (на основі 1) в межах набору ключових стовпців.

Я вважаю, що index_column_id(sys.index_column) і stats_column_id(sys.stats_columns) є еквівалентом один одному і що тільки таблиця sys.index_columns має стовпець упорядкування, а саме key_ordinal.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.