Là sys.stats_columns không chính xác?


28

Giả sử tôi có một bảng Foocó các cột ID1, ID2và khóa chính tổng hợp được xác định ID2, ID1. (Tôi hiện đang làm việc với một sản phẩm Trung tâm Hệ thống có một số bảng được xác định theo cách này với các cột khóa chính được liệt kê theo thứ tự ngược lại chúng xuất hiện trong định nghĩa bảng.)

CREATE TABLE dbo.Foo(
  ID1 int NOT NULL,
  ID2 int NOT NULL,
CONSTRAINT [PK_Foo] PRIMARY KEY CLUSTERED (ID2, ID1)
);
GO

-- Add a row and update stats so that histogram isn't empty
INSERT INTO Foo (ID1, ID2) VALUES (1,2);
UPDATE STATISTICS dbo.Foo;

Các key_ordinalcột trong sys.index_columnschương trình các cột chỉ số theo thứ tự chúng được khai báo trong khóa chính tổng hợp:

SELECT t.name, i.name, c.column_id, c.name, ic.index_column_id, ic.key_ordinal
FROM sys.tables AS t
JOIN sys.indexes AS i
ON t.[object_id] = i.[object_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 ic.column_id = c.column_id
AND ic.[object_id] = c.[object_id]
WHERE t.name = 'Foo';

mục lục

Biểu đồ cũng hiển thị số liệu thống kê theo thứ tự tương tự:

DBCC SHOW_STATISTICS ('Foo',PK_Foo);

số liệu thống kê

Tuy nhiên, sys.stats_columnshiển thị các cột được liệt kê theo thứ tự nghịch đảo ( ID1, ID2).

SELECT s.name, sc.stats_column_id, c.name
FROM sys.stats AS s
JOIN sys.stats_columns AS sc 
ON s.stats_id = sc.stats_id 
AND s.[object_id] = sc.[object_id] 
JOIN sys.columns AS c 
ON c.[object_id] = s.[object_id]
AND c.column_id = sc.column_id
JOIN sys.objects AS o 
ON o.[object_id] = c.[object_id] 
WHERE o.name = 'Foo'
AND s.name = 'PK_Foo';

số liệu thống kê

Books Online cho biết stats_column_idlà "thứ tự dựa trên 1 trong tập hợp các cột thống kê", vì vậy tôi đã mong đợi giá trị 1 sẽ trỏ đến cột đầu tiên trong đối tượng thống kê.

Đây có phải là một lỗi trong sys.stats_columnshoặc một sự hiểu lầm từ phía tôi?

Tôi đã xác minh hành vi này xảy ra trên các bản dựng hiện tại của SQL Server 2005, 2008, 2008 R2, 2012 và 2014.

sys.stats_columns dường như phản ánh thứ tự trong đối tượng thống kê trong các tình huống khác, ví dụ:

CREATE TABLE dbo.Foo2(
  ID1 int NOT NULL,
  ID2 int NOT NULL,
  ID3 int NULL,
  String VARCHAR(10) NULL,
CONSTRAINT [PK_Foo2] PRIMARY KEY CLUSTERED (ID2, ID1)
);

GO

INSERT INTO Foo2 (ID1, ID2, ID3, String) VALUES (1,2,3,'String');

CREATE STATISTICS ST_Test ON Foo2 (ID3, String);
CREATE STATISTICS ST_Test2 ON Foo2 (String, ID3);

DBCC SHOW_STATISTICS ('Foo2',ST_Test);
DBCC SHOW_STATISTICS ('Foo2',ST_Test2);


SELECT s.name, sc.stats_column_id, c.name
FROM sys.stats AS s
JOIN sys.stats_columns AS sc 
ON s.stats_id = sc.stats_id 
AND s.[object_id] = sc.[object_id] 
JOIN sys.columns AS c 
ON c.[object_id] = s.[object_id]
AND c.column_id = sc.column_id
JOIN sys.objects AS o 
ON o.[object_id] = c.[object_id] 
WHERE o.name = 'Foo2'
AND s.name LIKE 'ST_Test%';

morestats

Đây là một ví dụ khác sys.stats_columnsxuất hiện để trả về dữ liệu chính xác, lần này là để thống kê về một chỉ mục:

--drop table dbo.Foo3
CREATE TABLE dbo.Foo3(
  ID1 int NOT NULL,
  ID2 int NOT NULL,
  ID3 int NULL,
  String VARCHAR(10) NULL,
CONSTRAINT [PK_Foo3] PRIMARY KEY CLUSTERED (ID2, ID1)
);

GO

INSERT INTO Foo3 (ID1, ID2, ID3, String) VALUES (1,2,3,'String');
UPDATE STATISTICS Foo3;

CREATE INDEX IX_Test ON Foo3 (ID3, String);
CREATE INDEX IX_Test2 ON Foo3 (String, ID3);

DBCC SHOW_STATISTICS ('Foo3',IX_Test);
DBCC SHOW_STATISTICS ('Foo3',IX_Test2);

SELECT s.name, sc.stats_column_id, c.name
FROM sys.stats AS s
JOIN sys.stats_columns AS sc 
ON s.stats_id = sc.stats_id 
AND s.[object_id] = sc.[object_id] 
JOIN sys.columns AS c 
ON c.[object_id] = s.[object_id]
AND c.column_id = sc.column_id
JOIN sys.objects AS o 
ON o.[object_id] = c.[object_id] 
WHERE o.name = 'Foo3'
AND s.name LIKE 'IX_Test%';

moremorestats


3
Tôi đã có cùng một câu hỏi một vài tháng trước nhưng đã xóa nó. Xin lỗi vì điều đó. Tuy nhiên, stats_column_idtrong sys.stats_columnsdường như không làm những gì nó nói nó. Bởi vì bạn đang ủng hộ một chỉ mục, tôi sẽ tuân theo thứ tự cột chỉ mục. Nếu bạn chỉ nhìn vào các đối tượng thống kê thì có vẻ như đó index_col()là lựa chọn tốt nhất hiện tại
swasheck 5/03/2015

5
Có lẽ bạn nên / có thể gửi một mục Microsoft Connect cho việc này? Có vẻ lỗi với tôi.
Max Vernon

6
@MaxVernon, swashk đã nộp một cái ở đây
James L

Câu trả lời:


5

Đây có vẻ là một lỗi lâu dài:

swasheck - ngày 5 tháng 3 năm 2015 được đăng:

https://connect.microsoft.com/QueryServer/feedback/details/1163126

MSDN lưu ý rằng sys.stats_columns.stats_column_id là "thứ tự dựa trên 1 trong tập hợp các cột thống kê." Tuy nhiên, nó dường như thực sự phản ánh thứ tự định nghĩa bảng. Thay đổi thứ tự chỉ mục không được phản ánh trong sys.stats_columns.

Max Vernon và James Lupolt dường như đồng ý dựa trên ý kiến ​​/ khuyến khích của họ.

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.