stats_column_id và index_column_id không cập nhật với thứ tự vật lý của chỉ mục cụm được thay đổi


14

Trừ khi tôi hiểu sai mục đích của cột, đoạn mã sau chỉ ra rằng thay đổi cấu trúc của chỉ mục cụm không thay đổi vị trí thứ tự ( stats_column_id) của cột trong sys.stats_columns DMV. (Đã thử nghiệm trong 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;

Tuy nhiên, các vectơ mật độ cho thấy một sự thay đổi trong cột hàng đầu của đối tượng chỉ số / thống kê. Đây có phải là một sự hiểu lầm cơ bản về phía tôi? Nếu vậy, làm thế nào tôi có thể tìm thấy cột hàng đầu của một đối tượng thống kê sử dụng DMV?

Các phiên bản SQL Server đã kiểm tra: 2008R2, 2014


1
Không phải là cột_id vị trí thứ tự trong bảng ? Điều gì xảy ra nếu bạn thả và tạo lại bảng và thực sự thay đổi vị trí thứ tự của các cột đó? Tôi không có thời gian để kiểm tra ngay bây giờ nhưng tôi thấy thuận tiện một cách đáng ngờ rằng đó là 1,2,3 trong số liệu thống kê và 1,2,3 trong bảng và sys.columns.
Aaron Bertrand

@AaronBertrand có. và sau đó index_column_id là ... một cái gì đó ... và key_ordinallà thứ tự của các cột chỉ mục (chỉ cần phát hiện ra điều đó). tuy nhiên, tài liệu về sys.stats_columns dường như chỉ ra rằng stats_column_id là vị trí thứ tự, nhưng tôi có thể đọc được điều này hoàn toàn sai.
swasheck

2
Tôi đoán tôi chỉ có thể sử dụng INDEX_COL()mặc dù tôi mơ hồ nhớ lại ai đó lưu ý rằng các chức năng trợ giúp đó có thể không phải là ý tưởng tốt nhất
swasheck

Câu trả lời:


1

Bởi tất cả các tài khoản, đây có thể là một hành vi có lỗi trong DMV sys.stats_columns. Điều này dường như gây ra vấn đề khi một thống kê được cập nhật theo cách của chỉ số cha. Tôi tin rằng điều này là do cơ chế mà các số liệu thống kê đang được cập nhật trong một thay đổi ràng buộc.

Nếu bạn tạo một thống kê theo cách thủ công và sau đó muốn thay đổi các cột, trước tiên bạn phải thả và tạo lại, điều đó buộc dữ liệu meta phải được cập nhật trong DMV. Trong hoạt động bạn đã chứng minh có vẻ như có một tình huống mà siêu dữ liệu không được cập nhật trong bất kỳ trường hợp nào (DBCC *, CHECKPOINT, khởi động lại máy chủ, cập nhật thống kê thông qua thay đổi chỉ số cha mẹ, v.v.) sau khi thay đổi được thực hiện. Từ thử nghiệm ban đầu của tôi, tôi chỉ có thể tìm thấy một trường hợp khi siêu dữ liệu được cập nhật chính xác, đó là kịch bản thả và tạo lại.

Bạn có thể xem mục Kết nối về vấn đề này và bỏ phiếu khi thích hợp. Có một công việc xung quanh truy vấn được đăng ở đó nhưng cơ chế của nó dựa trên việc khớp tên chỉ mục với tên thống kê và sử dụng dữ liệu meta chỉ mục.


1

Tôi đã gặp vấn đề tương tự trong khi cố gắng tái tạo cách người khác lấy thông tin chỉ mục từ các khung nhìn sys.dm trong SQL Server. Tôi chỉ không thể tìm ra thứ tự của các cột trong chỉ mục.

Sau đây là tập lệnh tôi đã tạo để xác định thứ tự của các cột trong bất kỳ chỉ mục đã cho nào cho một bảng đã cho:

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

Cột key_ordinal trong bảng sys.index_columns là thứ tự mà các cột được lưu trữ trong chỉ mục.

Không có key_ordinal cột cho sys.stats_columnsbảng. Cột stats_column_idchỉ sao chép index_column_idcột của đối tượng mà nó tham chiếu.

Có một sự khác biệt nhỏ trong cách diễn đạt của bài viết sys.stats_columns (Transact-SQL) cho cột stats_column_id:

Thứ tự dựa trên 1 trong tập hợp các cột số liệu thống kê.

... và trong bài viết sys.index_columns (Transact-SQL) cho key_ordinalcột:

Thông thường (dựa trên 1) trong bộ khóa màu.

Tôi nghĩ rằng index_column_id(sys.index_columns) và stats_column_id(sys.stats_columns) tương đương với nhau và chỉ có bảng sys.index_columns có một cột đặt hàng, cụ thể là key_ordinal.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.