stats_column_id ve index_column_id, kümelenmiş dizinin fiziksel sırası değiştiğinde güncellenmiyor


14

Sütunun amacını yanlış anlamadığım sürece, aşağıdaki kod, kümelenmiş dizinin yapısındaki bir değişikliğin sys.stats_columns DMV'dekistats_column_id sütunun sıra konumunu ( ) değiştirmediğini gösterir . (AdventureWorks2014, AdventureWorks2008R2'de test edilmiştir)

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;

Bununla birlikte, yoğunluk vektörleri dizin / istatistik nesnesinin ön sütununda bir değişikliği gösterir. Bu benim için temel bir yanlış anlama mı? Öyleyse, DMV'leri kullanarak bir istatistik nesnesinin önde gelen sütununu nasıl bulabilirim?

Test edilen SQL Server sürümleri: 2008R2, 2014


1
Column_id , tablodaki sıralı konum değil mi? Tabloyu bırakıp yeniden oluşturup bu sütunların sıralı konumunu değiştirirseniz ne olur? Şu anda test etmek için zamanım yok ama bunların istatistiklerde 1,2,3 ve tabloda ve sys.columns'ta 1,2,3 olması şüpheyle uygun buluyorum.
Aaron Bertrand

@AaronBertrand evet. ve sonra index_column_id ... bir şey ... ve key_ordinaldizin sütunlarının sırasıdır (bunu keşfettim). Ancak, sys.stats_columns üzerindeki belgeler stats_column_id sıralı konum olduğunu gösteriyor gibi görünüyor, ama ben bu tamamen yanlış okuyor olabilir.
swasheck

2
i sadece INDEX_COL()bu yardımcı fonksiyonlar en iyi fikir olmayabilir dikkat çeken birileri hatırlıyorum rağmen ben sadece kullanabilirsiniz sanırım
swasheck

Yanıtlar:


1

Tüm hesaplar tarafından bu, sys.stats_columns DMV'de bir hata davranışı olabilir. Bu, bir istatistik üst dizin yoluyla güncellendiğinde sorunlara yol açıyor gibi görünüyor. Bunun, istatistiklerin bir kısıtlama değişikliğinde güncellenme mekanizmasından kaynaklandığına inanıyorum.

Elle bir istatistik oluşturursanız ve ardından sütunları değiştirmek isterseniz, önce söz konusu DMV'de güncellenmesi için meta verilerin zorlanmasına neden olacak şekilde düşürüp yeniden oluşturmanız gerekir. Gösterdiğiniz işlemde, değişiklik yapıldıktan sonra meta verilerin hiçbir koşulda (DBCC *, CHECKPOINT, sunucu yeniden başlatma, üst dizin değişikliği yoluyla istatistik güncelleme vb.) Güncellenmediği bir durum var gibi görünüyor. İlk testlerimden, meta veriler düzgün bir şekilde güncellendiğinde yalnızca bir örneği bulabilirim; bu, bırak ve yeniden oluştur senaryosu.

Konuyla ilgili Connect öğesine bir göz atabilir ve uygun şekilde oy kullanabilirsiniz. Orada gönderilen sorgu etrafında bir çalışma var, ancak mekanizması dizin adının istatistik adıyla eşleştirilmesi ve dizin meta verilerinin kullanılması dayanmaktadır.


1

Başkalarının SQL Server'da sys.dm görünümlerinden dizin bilgilerini almak şekilde yeniden oluşturmaya çalışırken aynı sorunu yaşıyordum. Dizindeki sütunların sırasını bulamadım.

Aşağıda, belirli bir tablo için herhangi bir dizindeki sütunların sırasını belirlemek için oluşturduğum bir komut dosyasıdır:

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

Sütun key_ordinalsys.index_columns tabloda sütun indeksi depolanır sıradır.

Tablo key_ordinaliçin bir sütun yok sys.stats_columns. Sütun stats_column_idsadece çoğaltır index_column_idbaşvurduğu nesnenin sütunu.

Sütun için sys.stats_columns (Transact-SQL) makalesinde küçük bir fark var stats_column_id:

İstatistik sütunları kümesinde 1 tabanlı sıra sayısı.

... ve makale içinde sys.index_columns (Transact-SQL) için key_ordinalsütunda:

Anahtar sütunlarında sıralı (1 tabanlı) .

Bunu hesaba katmak index_column_id(sys.index_columns) ve stats_column_id(sys.stats_columns) birbirine eşdeğerdir ve bu sadece sys.index_columns tablo, yani bir sipariş sütun vardır key_ordinal.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.