Является ли sys.stats_columns неверным?

28

Допустим, у меня есть таблица Fooсо столбцами ID1, ID2и составной первичный ключ, определенный поверх ID2, ID1. (В настоящее время я работаю с продуктом System Center, в котором несколько таблиц определены таким образом, а столбцы первичного ключа перечислены в обратном порядке, в котором они отображаются в определении таблицы.)

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;

key_ordinalСтолбец sys.index_columnsпоказывает индекс столбцов в том же порядке , как они были объявлены в составном первичном ключе:

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

показатель

Гистограмма также показывает статистику в том же порядке:

DBCC SHOW_STATISTICS ('Foo',PK_Foo);

статистика

Тем не менее, sys.stats_columnsпоказывает столбцы, перечисленные в обратном порядке ( 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 говорит, stats_column_idчто это «порядковый номер на основе 1 в наборе столбцов статистики», поэтому я ожидал, что значение 1 будет указывать на первый столбец в объекте статистики.

Это ошибка sys.stats_columnsили недоразумение с моей стороны?

Я проверял, что это происходит в текущих сборках SQL Server 2005, 2008, 2008 R2, 2012 и 2014.

sys.stats_columns кажется, отражает порядок в объекте статистики в других ситуациях, например:

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

Вот еще один пример, где, как sys.stats_columnsпредставляется, возвращаются правильные данные, на этот раз для статистики по индексу:

--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
У меня был тот же вопрос несколько месяцев назад, но я удалил его. Прости за это. Тем не менее, кажется , что stats_column_idin sys.stats_columnsне делает то, что говорит. Поскольку вы поддерживаете индекс, я бы придерживался порядка столбцов индекса. Если вы просто смотрите на объекты статистики, похоже, что index_col()это лучший вариант на данный момент
swasheck
5
Возможно, вы должны / могли бы подать элемент Microsoft Connect для этого? Кажется, глючит для меня.
Макс Вернон
6
@MaxVernon, swashesk подал один здесь
Джеймс Л

Ответы:

5

Это кажется давней ошибкой:

swasheck - 5 марта 2015 г.

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

MSDN отмечает, что sys.stats_columns.stats_column_id - это «порядковый номер на основе 1 в наборе столбцов статистики». Тем не менее, похоже, что он отражает порядок определения таблиц. Изменение порядка индексов не отражается в sys.stats_columns.

Макс Вернон и Джеймс Лупольт, кажется, соглашаются, основываясь на их комментариях / поддержке.

ДКП
источник