Diyelim ki Foo
sütunlara sahip bir masa ID1, ID2
ve üzerinde tanımlanmış bileşik bir birincil anahtar var ID2, ID1
. (Şu anda, tablo tanımında göründüğü ters sırada listelenen birincil anahtar sütunlarıyla bu şekilde tanımlanmış birkaç tablo içeren bir System Center ürünüyle çalışıyorum.)
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;
İçindeki key_ordinal
sütun sys.index_columns
, dizin sütunlarını, bileşik birincil anahtarda bildirildikleri sırayla gösterir:
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, istatistikleri aynı sırada gösterir:
DBCC SHOW_STATISTICS ('Foo',PK_Foo);
Ancak, sys.stats_columns
ters sırada listelenen sütunları ( ID1, ID2
) gösterir.
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 Onlinestats_column_id
, "istatistik sütunları kümesinde 1 tabanlı bir sıra" olduğunu söylüyor , bu nedenle, 1 değerinin istatistik nesnesindeki ilk sütuna işaret etmesini bekliyordum.
Bu sys.stats_columns
benim açımdan bir hata mı, yoksa yanlış bir anlama mı geliyor?
Bu davranışın, SQL Server 2005, 2008, 2008 R2, 2012 ve 2014'ün geçerli sürümlerinde gerçekleştiğini doğruladım.
sys.stats_columns
Örneğin, istatistik nesnesi içindeki sırayı diğer durumlarda yansıtıyor gibi görünüyor:
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%';
İşte sys.stats_columns
doğru verileri döndürdüğü başka bir örnek: bu sefer bir dizindeki istatistikler için:
--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
içindesys.stats_columns
bunu söylüyor ne yapacağını görünmüyor. Bir dizini desteklediğiniz için, dizin sütunu sırasına bağlı kalacağım. Sadece istatistikleri bakıyorsanız gibi görünüyor nesneleriindex_col()
en iyi şu anda seçenektir