Apakah sys.stats_columns salah?

28

Katakanlah saya memiliki tabel Foodengan kolom ID1, ID2dan kunci primer komposit yang ditentukan ID2, ID1. (Saat ini saya sedang bekerja dengan produk System Center yang memiliki beberapa tabel didefinisikan dengan cara ini dengan kolom kunci utama yang tercantum dalam urutan yang berlawanan mereka muncul dalam definisi tabel.)

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;

The key_ordinalkolom dalam sys.index_columnsacara kolom indeks dalam urutan yang sama mereka dinyatakan dalam kunci primer komposit:

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';

indeks

Histogram juga menunjukkan statistik dalam urutan yang sama:

DBCC SHOW_STATISTICS ('Foo',PK_Foo);

statistik

Namun, sys.stats_columnsmemperlihatkan kolom yang tercantum dalam urutan terbalik ( 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';

stats_columns

Books Online mengatakan stats_column_idadalah "ordinal 1-based dalam set kolom statistik," jadi saya mengharapkan nilai 1 untuk menunjuk ke kolom pertama dalam objek statistik.

Apakah ini bug di sys.stats_columns atau kesalahpahaman di pihak saya?

Saya telah memverifikasi perilaku ini terjadi pada build SQL Server 2005, 2008, 2008 R2, 2012, dan 2014 saat ini.

sys.stats_columns tampaknya mencerminkan urutan dalam objek statistik dalam situasi lain, misalnya:

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

Berikut adalah contoh lain di mana sys.stats_columnsmuncul untuk mengembalikan data yang benar, kali ini untuk statistik pada indeks:

--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

James L
sumber
3
Saya memiliki pertanyaan yang sama beberapa bulan yang lalu tetapi menghapusnya. Maaf soal itu. Meskipun demikian, stats_column_iddi sys.stats_columnstampaknya tidak melakukan apa yang dikatakannya itu tidak. Karena Anda mendukung indeks, saya akan tetap dengan urutan kolom indeks. Jika Anda hanya melihat objek statistik sepertinya itu index_col()pilihan terbaik saat ini
swasheck
5
Mungkin Anda harus / bisa mengajukan item Microsoft Connect untuk ini? Sepertinya buggy bagiku.
Max Vernon
6
@ MaxVernon, swashesk telah mengajukan satu di sini
James L

Jawaban:

5

Ini tampaknya merupakan kesalahan lama:

swasheck - 5 Maret 2015 diposting:

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

MSDN mencatat bahwa sys.stats_columns.stats_column_id adalah "ordinal berbasis 1 dalam set kolom statistik." Namun, tampaknya sebenarnya mencerminkan urutan definisi tabel. Mengubah urutan indeks tidak tercermin di sys.stats_columns.

Max Vernon dan James Lupolt tampaknya setuju berdasarkan komentar / dorongan mereka.

RLF
sumber