stats_column_id und index_column_id werden nicht aktualisiert, wenn die physische Reihenfolge des Clustered-Index geändert wird

14

Sofern ich den Zweck der Spalte nicht falsch verstehe , gibt der folgende Code an, dass eine Änderung der Struktur des Clustered-Index die Ordnungsposition ( stats_column_id) der Spalte in der DMV sys.stats_columns nicht ändert . (Getestet in 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;

Die Dichtevektoren zeigen jedoch eine Änderung in der führenden Spalte des Index- / Statistikobjekts an. Ist das ein grundsätzliches Missverständnis meinerseits? Wenn ja, wie würde ich die führende Spalte eines Statistikobjekts mithilfe von DMVs finden?

Getestete SQL Server-Versionen: 2008R2, 2014

Swasheck
quelle
1
Ist die column_id nicht die Ordnungszahl in der Tabelle ? Was passiert, wenn Sie die Tabelle löschen und neu erstellen und die Ordnungsposition dieser Spalten tatsächlich ändern? Ich habe momentan keine Zeit zum Testen, aber ich finde es verdächtig bequem, dass dies 1,2,3 in der Statistik und 1,2,3 in der Tabelle und in sys.columns sind.
Aaron Bertrand
@ AaronBertrand ja. und dann ist index_column_id ... etwas ... und key_ordinalist die Reihenfolge der Indexspalten (soeben entdeckt). Die Dokumentation auf sys.stats_columns scheint jedoch darauf hinzudeuten, dass stats_column_id die Ordnungsposition ist, aber ich könnte dies völlig falsch lesen.
Swasheck
2
Ich denke, ich könnte es nur gebrauchen, INDEX_COL()obwohl ich mich vage an jemanden erinnere, der bemerkt hat, dass diese
Hilfsfunktionen

Antworten:

1

In allen Konten ist dies möglicherweise ein fehlerhaftes Verhalten in der DMV "sys.stats_columns". Dies scheint Probleme zu verursachen, wenn eine Statistik über den übergeordneten Index aktualisiert wird. Ich glaube, dass dies auf den Mechanismus zurückzuführen ist, mit dem die Statistiken bei einer Einschränkungsänderung aktualisiert werden.

Wenn Sie eine Statistik manuell erstellen und dann die Spalten ändern möchten, müssen Sie diese zuerst löschen und neu erstellen, wodurch die Aktualisierung der Metadaten in der betreffenden DMV erzwungen wird. In der von Ihnen gezeigten Operation scheint es eine Situation zu geben, in der die Metadaten nach der Änderung unter keinen Umständen aktualisiert werden (DBCC *, CHECKPOINT, Neustart des Servers, Aktualisierung der Statistiken durch Änderung des übergeordneten Index usw.). Nach meinen ersten Tests kann ich nur einen Fall finden, in dem die Metadaten ordnungsgemäß aktualisiert wurden. Dies ist das Szenario zum Löschen und Neuerstellen.

Sie können einen Blick auf den Connect-Artikel werfen und gegebenenfalls abstimmen. Dort wird eine Problemumgehungsabfrage veröffentlicht, deren Mechanismus darauf basiert, den Indexnamen mit dem Statistiknamen abzugleichen und die Index-Metadaten zu verwenden.

Travis Page
quelle
1

Ich hatte das gleiche Problem beim Versuch zu reproduzieren, wie andere Indexinformationen aus den sys.dm-Ansichten in SQL Server abrufen. Ich konnte nur die Reihenfolge der Spalten im Index nicht herausfinden.

Es folgt ein Skript, das ich erstellt habe, um die Reihenfolge der Spalten in einem bestimmten Index für eine bestimmte Tabelle zu bestimmen:

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

Die Spalte key_ordinalin der Tabelle sys.index_columns gibt die Reihenfolge an, in der die Spalten im Index gespeichert sind.

Es gibt keine key_ordinalSpalte für die sys.stats_columnsTabelle. Die Spalte stats_column_idrepliziert nur die index_column_idSpalte des Objekts, auf das sie verweist.

Es gibt einen kleinen Unterschied im Wortlaut des Artikels sys.stats_columns (Transact-SQL) für die Spalte stats_column_id:

1-basierte Ordnungszahl innerhalb der Statistikspalten.

... und im Artikel sys.index_columns (Transact-SQL) für die key_ordinalSpalte:

Ordnungszahl (1-basiert) innerhalb eines Satzes von Schlüsselspalten .

Ich index_column_idgehe davon aus, dass die Spalten (sys.index_columns) und stats_column_id(sys.stats_columns) einander entsprechen und dass nur die Tabelle sys.index_columns eine Ordnungsspalte enthält, nämlich key_ordinal.

John aka hot2use
quelle