Ist sys.stats_columns falsch?

28

Angenommen, ich habe eine Tabelle Foomit Spalten ID1, ID2und einem über definierten zusammengesetzten Primärschlüssel ID2, ID1. (Ich arbeite derzeit mit einem System Center-Produkt, für das mehrere Tabellen auf diese Weise definiert wurden, wobei die Primärschlüsselspalten in der umgekehrten Reihenfolge aufgeführt sind, in der sie in der Tabellendefinition angezeigt werden.)

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;

Die key_ordinalSpalte in sys.index_columnszeigt die Indexspalten in derselben Reihenfolge, in der sie im zusammengesetzten Primärschlüssel deklariert wurden:

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

Index

Das Histogramm zeigt auch die Statistiken in der gleichen Reihenfolge:

DBCC SHOW_STATISTICS ('Foo',PK_Foo);

Statistiken

Jedoch sys.stats_columnszeigt die Spalten in der umgekehrten Reihenfolge ( 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

Die Onlinedokumentation gibt an, dass stats_column_ides sich um eine "1-basierte Ordnungszahl innerhalb eines Satzes von Statistikspalten" handelt. Ich habe daher erwartet, dass der Wert 1 auf die erste Spalte im Statistikobjekt verweist.

Ist das ein Fehler sys.stats_columnsoder ein Missverständnis von meiner Seite?

Ich habe überprüft, ob dieses Verhalten bei aktuellen Versionen von SQL Server 2005, 2008, 2008 R2, 2012 und 2014 auftritt.

sys.stats_columns scheint die Reihenfolge innerhalb des Statistikobjekts in anderen Situationen widerzuspiegeln, zum Beispiel:

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

Hier ist ein weiteres Beispiel, in sys.stats_columnsdem die korrekten Daten angezeigt werden, diesmal für Statistiken zu einem Index:

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

mehrmorestats

James L
quelle
3
Ich hatte vor ein paar Monaten die gleiche Frage, habe sie aber gelöscht. Das tut mir leid. Dennoch ist die stats_column_idin sys.stats_columnsnicht scheinen zu tun , was sie sagt , es tut. Da Sie einen Index sichern, halte ich mich an die Reihenfolge der Indexspalten. Wenn Sie sich nur Statistikobjekte index_col()
ansehen,
5
Vielleicht sollten / könnten Sie dafür ein Microsoft Connect-Objekt einreichen? Scheint mir buggy.
Max Vernon
6
@MaxVernon, swashesk hat hier
James L

Antworten:

5

Dies scheint ein langjähriger Fehler zu sein:

swasheck - 5. März 2015 gepostet:

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

MSDN stellt fest, dass sys.stats_columns.stats_column_id "1-basierte Ordnungszahl innerhalb einer Reihe von Statistikspalten" ist. Es scheint jedoch tatsächlich die Reihenfolge der Tabellendefinitionen widerzuspiegeln. Das Ändern der Indexreihenfolge wird in sys.stats_columns nicht berücksichtigt.

Max Vernon und James Lupolt scheinen sich aufgrund ihrer Kommentare / Ermutigungen einig zu sein.

RLF
quelle