Sys.stats_columns è errato?


28

Diciamo che ho una tabella Foocon colonne ID1, ID2e una chiave primaria composita definita sopra ID2, ID1. (Attualmente sto lavorando con un prodotto System Center che ha diverse tabelle definite in questo modo con le colonne chiave primaria elencate nell'ordine opposto che appaiono nella definizione della tabella.)

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;

La key_ordinalcolonna in sys.index_columnsmostra le colonne dell'indice nello stesso ordine in cui sono state dichiarate nella chiave primaria composita:

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

indice

L'istogramma mostra anche le statistiche nello stesso ordine:

DBCC SHOW_STATISTICS ('Foo',PK_Foo);

statistiche

Tuttavia, sys.stats_columnsmostra le colonne elencate nell'ordine inverso ( 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 dice che stats_column_idè un "ordinale basato su 1 all'interno di un insieme di colonne di statistiche", quindi mi aspettavo che il valore 1 puntasse alla prima colonna nell'oggetto statistico.

È un errore sys.stats_columnso un malinteso da parte mia?

Ho verificato che questo comportamento si verifica nelle build correnti di SQL Server 2005, 2008, 2008 R2, 2012 e 2014.

sys.stats_columns sembra riflettere l'ordine all'interno dell'oggetto statistico in altre situazioni, ad esempio:

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

Ecco un altro esempio in cui sys.stats_columnssembra restituire i dati corretti, questa volta per le statistiche su un indice:

--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
Ho avuto la stessa domanda qualche mese fa ma l'ho cancellata. Mi dispiace per quello. Nondimeno, stats_column_idin sys.stats_columnsnon sembra fare quello che dice di fare. Poiché stai supportando un indice, rimarrei con l'ordine delle colonne dell'indice. Se stai solo guardando gli oggetti stats, sembra che index_col()sia l'opzione migliore al momento
scambia il

5
Forse dovresti / potresti presentare un articolo di Microsoft Connect per questo? Mi sembra buggy.
Max Vernon,

6
@MaxVernon, swashesk ne ha archiviato uno qui
James L

Risposte:


5

Questo sembra essere un errore di vecchia data:

swasheck - 5 marzo 2015 pubblicato:

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

MSDN osserva che sys.stats_columns.stats_column_id è "ordinale basato su 1 all'interno di un insieme di colonne di statistiche". Tuttavia, sembra riflettere effettivamente l'ordine di definizione della tabella. La modifica dell'ordine degli indici non si riflette in sys.stats_columns.

Max Vernon e James Lupolt sembrano concordare sulla base dei loro commenti / incoraggiamento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.