列の目的を誤解していない限り、次のコードは、クラスター化インデックスの構造を変更しても順序位置(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
すべてのアカウントで、これはsys.stats_columns DMVのバグのある動作である可能性があります。これは、統計が親インデックスを介して更新されるときに問題を引き起こしているようです。これは、制約の変更時に統計が更新されるメカニズムが原因であると考えています。
統計を手動で作成してから列を変更する場合は、まずドロップして再作成する必要があります。これにより、問題のDMVでメタデータが強制的に更新されます。変更を加えた後、メタデータがどのような状況(DBCC *、CHECKPOINT、サーバーの再起動、親インデックスの変更による統計の更新など)でも更新されない状況があることが、操作で示されました。最初のテストから、メタデータが適切に更新された場合に1つだけのケースを見つけることができます。これは、ドロップと再作成のシナリオです。
問題について Connect item を確認し、必要に応じて賛成票を投じてください。そこに投稿されたクエリには回避策がありますが、そのメカニズムは、インデックス名を統計名と照合し、インデックスメタデータを利用することに基づいています。
他のユーザーが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
Sys.index_columnsテーブルの列key_ordinal
は、列がインデックスに格納される順序です。
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
列:
key列のセット内の序数(1ベース)。
index_column_id
(sys.index_columns)とstats_column_id
(sys.stats_columns)は互いに同等であり、sys.index_columnsテーブルのみがkey_ordinal
という順序列を持っていると思います。