Disons que j'ai une table Foo
avec des colonnes ID1, ID2
et une clé primaire composite définie sur ID2, ID1
. (Je travaille actuellement avec un produit System Center qui a plusieurs tables définies de cette façon avec les colonnes de clé primaire répertoriées dans l'ordre inverse de leur apparition dans la définition de table.)
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_ordinal
colonne dans sys.index_columns
affiche les colonnes d'index dans le même ordre qu'elles ont été déclarées dans la clé primaire composite:
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';
L'histogramme montre également les statistiques dans le même ordre:
DBCC SHOW_STATISTICS ('Foo',PK_Foo);
Cependant, sys.stats_columns
affiche les colonnes répertoriées dans l'ordre inverse ( 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';
Books Online indique qu'il stats_column_id
s'agit d'un "ordinal basé sur 1 dans un ensemble de colonnes de statistiques", donc je m'attendais à ce que la valeur 1 pointe vers la première colonne de l'objet de statistiques.
Est-ce un bug sys.stats_columns
ou un malentendu de ma part?
J'ai vérifié que ce problème se produit sur les versions actuelles de SQL Server 2005, 2008, 2008 R2, 2012 et 2014.
sys.stats_columns
semble refléter l'ordre dans l'objet statistique dans d'autres situations, par exemple:
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%';
Voici un autre exemple où sys.stats_columns
semble renvoyer les données correctes, cette fois pour les statistiques sur un 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%';
la source
stats_column_id
insys.stats_columns
ne semble pas faire ce qu'il dit. Parce que vous sauvegardez un index, je m'en tiendrai à l'ordre des colonnes d'index. Si vous regardez simplement les objets statistiques, il semble queindex_col()
c'est la meilleure option actuellementRéponses:
Cela semble être une erreur de longue date:
swasheck - 5 mars 2015 publié:
https://connect.microsoft.com/SQLServer/feedback/details/1163126
Max Vernon et James Lupolt semblent être d'accord sur la base de leurs commentaires / encouragements.
la source