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 ในสถิติและ 1,2,3 ในตารางและ sys.columns
Aaron Bertrand

@AaronBertrand ใช่ แล้ว index_column_id คือ ... บางอย่าง ... และkey_ordinalเป็นลำดับของคอลัมน์ดัชนี (เพิ่งค้นพบสิ่งนั้น) อย่างไรก็ตามเอกสารเกี่ยวกับ sys.stats_columns ดูเหมือนจะระบุว่า stats_column_id เป็นตำแหน่งอันดับ แต่ฉันอาจจะอ่านผิดนี้อย่างสมบูรณ์
swasheck

2
ฉันเดาว่าฉันสามารถใช้งานได้INDEX_COL()แม้ว่าฉันจะนึกถึงบางคนที่สังเกตว่าการทำงานของผู้ช่วยเหล่านั้นอาจไม่ใช่ความคิดที่ดีที่สุด
swasheck

คำตอบ:


1

โดยบัญชีทั้งหมดนี่อาจเป็นพฤติกรรมบั๊กใน sys.stats_columns DMV สิ่งนี้ดูเหมือนว่าจะก่อให้เกิดปัญหาเมื่อมีการอัปเดตสถิติโดยวิธีการของดัชนีหลัก ฉันเชื่อว่าสิ่งนี้เกิดจากกลไกที่สถิติถูกอัพเดตในการเปลี่ยนแปลงข้อ จำกัด

หากคุณสร้างสถิติด้วยตนเองและต้องการเปลี่ยนคอลัมน์คุณต้องวางและสร้างใหม่ซึ่งบังคับให้ meta-data อัปเดตใน DMV ที่เป็นปัญหา ในการดำเนินการที่คุณแสดงให้เห็นว่าดูเหมือนจะเป็นสถานการณ์ที่ข้อมูลเมตาไม่ได้รับการปรับปรุงภายใต้สถานการณ์ใด ๆ (DBCC *, CHECKPOINT, การรีสตาร์ทเซิร์ฟเวอร์การอัพเดตสถิติผ่านการเปลี่ยนแปลงดัชนีพาเรนต์เป็นต้น) เมื่อมีการเปลี่ยนแปลง จากการทดสอบครั้งแรกของฉันฉันสามารถค้นหาได้เพียงกรณีเดียวเมื่อข้อมูลเมตาได้รับการปรับปรุงอย่างถูกต้องซึ่งเป็นสถานการณ์การปล่อยและสร้างใหม่อีกครั้ง

คุณสามารถดูรายการเชื่อมต่อในปัญหาและโหวตขึ้นตามความเหมาะสม มีวิธีแก้ไขแบบสอบถามที่โพสต์ไว้ที่นั่น แต่กลไกของมันนั้นขึ้นอยู่กับการจับคู่ชื่อดัชนีกับชื่อสถิติและการใช้ดัชนี meta-data


1

ฉันมีปัญหาเดียวกันในขณะที่พยายามทำซ้ำวิธีที่คนอื่นดึงข้อมูลดัชนีจากมุมมอง sys.dm ใน SQL Server ฉันไม่สามารถหาลำดับของคอลัมน์ในดัชนีได้

ต่อไปนี้เป็นสคริปต์ที่ฉันสร้างขึ้นเพื่อกำหนดลำดับของคอลัมน์ในดัชนีที่กำหนดสำหรับตารางที่กำหนด:

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_ordinalในตาราง sys.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.