Katakanlah saya memiliki tabel Foo
dengan kolom ID1, ID2
dan 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_ordinal
kolom dalam sys.index_columns
acara 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';
Histogram juga menunjukkan statistik dalam urutan yang sama:
DBCC SHOW_STATISTICS ('Foo',PK_Foo);
Namun, sys.stats_columns
memperlihatkan 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';
Books Online mengatakan stats_column_id
adalah "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%';
Berikut adalah contoh lain di mana sys.stats_columns
muncul 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%';
stats_column_id
disys.stats_columns
tampaknya 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 ituindex_col()
pilihan terbaik saat ini