Jam*_*olt 28 sql-server statistics
假设我有一个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;
Run Code Online (Sandbox Code Playgroud)
的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';
Run Code Online (Sandbox Code Playgroud)

直方图还以相同的顺序显示统计信息:
DBCC SHOW_STATISTICS ('Foo',PK_Foo);
Run Code Online (Sandbox Code Playgroud)

但是,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';
Run Code Online (Sandbox Code Playgroud)

Books Online说stats_column_id是“一组 stats 列中的基于 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%';
Run Code Online (Sandbox Code Playgroud)

这是另一个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%';
Run Code Online (Sandbox Code Playgroud)

这似乎是一个长期存在的错误:
swasheck - 2015 年 3 月 5 日发布:
https://connect.microsoft.com/SQLServer/feedback/details/1163126
MSDN 指出 sys.stats_columns.stats_column_id 是“统计列集中的基于 1 的序数”。但是,它似乎实际上反映了表定义顺序。更改索引顺序未反映在 sys.stats_columns 中。
Max Vernon 和 James Lupolt 基于他们的评论/鼓励似乎同意。
| 归档时间: |
|
| 查看次数: |
896 次 |
| 最近记录: |