stats_column_idとindex_column_idは、クラスター化インデックスの物理的な順序が変更されても更新されません


14

列の目的を誤解していない限り、次のコードは、クラスター化インデックスの構造を変更stats_column_idしてもsys.stats_columns DMVの列の順序位置()が変更されないことを示しています。(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
column_id はテーブル内の序数位置はありませんか?テーブルをドロップして再作成し、実際にそれらの列の順序位置を変更するとどうなりますか?今すぐテストする時間はありませんが、統計では1,2,3であり、テーブルとsys.columnsでは1,2,3であることが疑わしく便利です。
アーロンバートランド

@AaronBertrandはい。そして、index_column_idは...何か...でありkey_ordinal、インデックス列の順序です(ちょうどそれを発見しました)。ただし、sys.stats_columnsのドキュメントは、stats_column_idが序数位置であることを示しているようですが、これは完全に間違っている可能性があります。
swasheck

2
私はちょうどINDEX_COL()それらのヘルパー機能が最高のアイデアではないかもしれないことに気づいた誰かを漠然と思い出すけれども使用できると思います
スワッシュック

回答:


1

すべてのアカウントで、これはsys.stats_columns DMVのバグのある動作である可能性があります。これは、親インデックスを使用して統計が更新されるときに問題を引き起こすようです。これは、制約が変更されたときに統計が更新されるメカニズムが原因であると考えています。

統計を手動で作成してから列を変更する場合は、最初に削除して再作成する必要があります。これにより、問題のDMVでメタデータが強制的に更新されます。実証した操作では、変更が行われると、どのような状況(DBCC *、CHECKPOINT、サーバーの再起動、親インデックスの変更による統計の更新など)でもメタデータが更新されない状況があります。最初のテストから、メタデータが適切に更新された場合、ドロップアンドリクリエイトシナリオであるケースが1つしか見つかりません。

問題のConnect項目を見て、必要に応じて投票することができます。そこに投稿されたクエリの回避策がありますが、そのメカニズムは、インデックス名を統計名に一致させ、インデックスメタデータを利用することに基づいています。


1

他の人がSQL Serverのsys.dmビューからインデックス情報を取得する方法を再現しようとしたときに、同じ問題が発生していました。インデックス内の列の順序がわかりませんでした。

以下は、特定のテーブルの特定のインデックスの列の順序を決定するために作成したスクリプトです。

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_ordinalsys.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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.