Sys.stats_columns hatalı mı?


28

Diyelim ki Foosütunlara sahip bir masa ID1, ID2ve ü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_ordinalsü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';

indeks

Histogram, istatistikleri aynı sırada gösterir:

DBCC SHOW_STATISTICS ('Foo',PK_Foo);

istatistikler

Ancak, sys.stats_columnsters 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';

stats_columns

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

morestats

İşte sys.stats_columnsdoğ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%';

moremorestats


3
Birkaç ay önce aynı soruyu yaşadım ama sildim. Bunun için üzgünüm. Bununla birlikte, stats_column_idiçinde sys.stats_columnsbunu 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 nesneleri index_col()en iyi şu anda seçenektir
swasheck

5
Belki de bunun için bir Microsoft Connect ürününü dosyalamalı / yapmalısınız? Bana adam gibi geliyor.
Max Vernon

6
@MaxVernon, swashesk burada bir
James L

Yanıtlar:


5

Bu uzun süredir devam eden bir hata gibi görünüyor:

kundak - 5 Mart 2015 tarihinde gönderildi:

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

MSDN, sys.stats_columns.stats_column_id'nin "istatistik sütun kümesinde 1 tabanlı sıra" olduğunu belirtir. Ancak, aslında tablo tanım sırasını yansıtıyor gibi görünüyor. Dizin sırasının değiştirilmesi sys.stats_columns dosyasına yansıtılmaz.

Max Vernon ve James Lupolt, yorumlarına / teşviklerine dayanarak aynı fikirde görünüyorlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.