Pour ceux qui se demandent comment interpréter les noms de statistiques créées automatiquement par l’optimisateur de requêtes ce billet est pour vous . Comme vous le savez sans doute lorsqu’un index créé des statistiques lui sont également associées. Ces dernières servent à l’optimisateur de requêtes afin de déterminer un plan optimal pour retrouver les données initiés par une requête. Autrement dit en fonction des cardinalités ou de la sélectivité des données sous jacentes celui-ci va déterminer quelle(s) méthode(s) il devra pour utiliser pour les retrouver avec un minimum de coût. Cependant que se passe-t-il lorsqu’une requête composée d’un prédicat ne concerne pas un index ? He bien celui-ci va créer des statistiques sur la ou les colonnes concernées pour pouvoir estimer la cardinalité des données à retourner. Ces statistiques se retrouvent sous la forme _WA_Sys_00000004_0F382DC6 par exemple. Comment interpréter ce nom plutôt abscons à première vue. C’est ce que nous allons voir dans la suite de billet.
En réalité la décomposition du nom fourni par l’optimisateur n’est pas très compliquée, encore faut-il savoir le décomposer.
_WA_Sys_00000004_0F382DC6 :Â
_WA_Sys_ | Préfixe donné par l’optimiseur de requêtes pour une statistique créée automatiquement |
00000004 | Valeur hexadécimale du numéro de colonne de la table concernée par la statistique créée automatiquement |
0F382DC6 | Valeur hexadécimale de l’Id de la table concernée par la statistique créée automatiquement |
Pour résumée une statique auto incrémentée est identifiée par l’Id de la table et le numéro de la colonne qui est concernée par notre statistique.
Voici une fonction (seulement pour s’amuser) qui permet de retrouver toutes ces informations :
CREATE FUNCTION stat_details (@stat_name SYSNAME)
RETURNS TABLE
AS
RETURN
(
SELECT OBJECT_NAME(CAST(CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(REVERSE(@stat_name), 1, CHARINDEX(‘_’, REVERSE(@stat_name)) – 1)), 2) AS INT)) AS table_name,
name AS column_name
FROM sys.columns
WHERE object_id = CAST(CONVERT(VARBINARY(MAX), REVERSE(SUBSTRING(REVERSE(@stat_name), 1, CHARINDEX(‘_’, REVERSE(@stat_name)) – 1)), 2) AS INT)
 AND column_id = CAST(CONVERT(VARBINARY(MAX), SUBSTRING(SUBSTRING(@stat_name, LEN(‘_WA_Sys_’) + 1, LEN(@stat_name)), 1, CHARINDEX(‘_’, SUBSTRING(@stat_name, LEN(‘_WA_Sys_’) + 1, LEN(@stat_name))) – 1) , 2) AS INT)
)
On peut l’utiliser comme ceci :
USE AdventureWorks;
GOSELECT
s.name,
c.table_name,
c.column_name
FROM sys.stats AS s
CROSS APPLY dbo.stat_details(s.name) AS c
WHERE s.object_id = OBJECT_ID(‘dbo.SalesOrderDetail’)
AND s.auto_created = 1; — Statistique créée automatiquement par l’optimiseur
Â
J’ai bien précisé pour s’amuser avec les valeurs hexadécimales  … on peut bien sûr retrouver ce même résultat plus facilement en utilisant une autre DMV adéquate sys.stat_columns :
SELECT
s.name,
o.name AS table_name,
c.name AS colum_name
FROM sys.stats_columns AS sc
JOIN sys.objects AS o
 ON sc.object_id = o.object_id
JOIN sys.stats AS s
 on s.stats_id = sc.stats_id
  AND s.object_id = o.object_id
JOIN sys.columns AS c
 on c.object_id = sc.object_id
  AND c.column_id = sc.column_id
WHERE o.object_id = OBJECT_ID(‘dbo.SalesOrderDetail’)
AND s.auto_created = 1;
Â
Bonne statistique !!
David BARBARIN (Mikedavem)
MVP SQL Server