stats_column_id dan index_column_id tidak diperbarui dengan urutan fisik indeks berkerumun diubah

14

Kecuali saya salah memahami tujuan kolom, kode berikut menunjukkan bahwa perubahan struktur indeks berkerumun tidak mengubah posisi ordinal ( stats_column_id) kolom dalam sys.stats_columns DMV. (Diuji dalam 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;

Namun, vektor kepadatan menunjukkan perubahan di kolom terkemuka objek indeks / statistik. Apakah ini kesalahpahaman mendasar di pihak saya? Jika demikian, bagaimana cara menemukan kolom utama objek statistik menggunakan DMV?

Versi SQL Server yang diuji: 2008R2, 2014

swasheck
sumber
1
Bukankah column_id posisi ordinal dalam tabel ? Apa yang terjadi jika Anda menjatuhkan dan membuat ulang tabel dan benar-benar mengubah posisi ordinal kolom tersebut? Saya tidak punya waktu untuk menguji sekarang tetapi saya merasa nyaman nyaman bahwa itu adalah 1,2,3 dalam statistik dan 1,2,3 dalam tabel dan sys.columns.
Aaron Bertrand
@ AaronBertrand ya. dan kemudian index_column_id adalah ... sesuatu ... dan key_ordinalmerupakan urutan kolom indeks (baru saja menemukan itu). Namun, dokumentasi pada sys.stats_columns tampaknya menunjukkan bahwa stats_column_id adalah posisi ordinal, tetapi saya bisa membaca ini sepenuhnya salah.
swasheck
2
Saya kira saya hanya dapat menggunakan INDEX_COL()meskipun saya samar-samar ingat seseorang yang mencatat bahwa fungsi pembantu mungkin bukan ide terbaik
swasheck

Jawaban:

1

Oleh semua akun ini mungkin perilaku disadap di sys.stats_columns DMV. Ini tampaknya menyebabkan masalah ketika statistik diperbarui dengan indeks induk. Saya percaya ini karena mekanisme pembaruan statistik dalam perubahan kendala.

Jika Anda membuat statistik secara manual dan kemudian ingin mengubah kolom, Anda harus terlebih dahulu menjatuhkan dan membuat kembali yang memaksa meta-data diperbarui di DMV yang bersangkutan. Dalam operasi yang telah Anda tunjukkan, tampaknya ada situasi di mana metadata tidak diperbarui dalam keadaan apa pun (DBCC *, CHECKPOINT, server restart, pembaruan statistik melalui perubahan indeks induk, dll) setelah perubahan telah dibuat. Dari pengujian awal saya, saya hanya dapat menemukan satu kasus ketika metadata diperbarui dengan benar yang merupakan skenario drop dan re-create.

Anda dapat melihat item Connect pada masalah dan pilih suara yang sesuai. Ada pekerjaan seputar kueri yang diposting di sana, tetapi mekanismenya didasarkan pada pencocokan nama indeks dengan nama statistik dan memanfaatkan meta-data indeks.

Halaman Travis
sumber
1

Saya mengalami masalah yang sama ketika mencoba mereproduksi cara orang lain mengambil informasi indeks dari tampilan sys.dm di SQL Server. Saya hanya tidak tahu urutan kolom dalam indeks.

Berikut ini adalah skrip yang saya buat untuk menentukan urutan kolom dalam indeks yang diberikan untuk tabel tertentu:

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

Kolom key_ordinaldalam tabel sys.index_columns adalah urutan penyimpanan kolom dalam indeks.

Tidak ada key_ordinalkolom untuk sys.stats_columnstabel. Kolom stats_column_idhanya mereplikasi index_column_idkolom dari objek yang dirujuk.

Ada sedikit perbedaan dalam kata-kata dari artikel sys.stats_columns (Transact-SQL) untuk kolom stats_column_id:

Urutan 1 berdasarkan dalam set kolom statistik.

... dan di artikel sys.index_columns (Transact-SQL) untuk key_ordinalkolom:

Ordinal (1-based) dalam set - kolom kunci .

Saya rasa bahwa index_column_id(sys.index_columns) dan stats_column_id(sys.stats_columns) adalah setara satu sama lain dan bahwa hanya tabel sys.index_columns memiliki kolom pemesanan, yaitu key_ordinal.

John alias hot2use
sumber