Où les statistiques sont-elles physiquement stockées dans SQL Server?


27

Où les statistiques utilisées par l'Optimiseur de requête sont-elles physiquement stockées dans un fichier de base de données SQL Server et le pool de tampons?

Plus précisément, existe-t-il un moyen de comprendre les pages utilisées par les statistiques à l'aide de DMV et / ou DBCC?

Je possède à la fois des livres sur SQL Server 2008 Internals et SQL Server Internals and Troubleshooting et aucun d'eux ne parle de la structure physique des statistiques; s'ils le font, je ne pourrai pas trouver cette information.


1
Lorsque vous créez une copie de statistiques uniquement de la base de données, il montre un binaire que STATS_STREAMje n'ai jamais vérifié si c'est quelque chose de trouvable dans le fichier lui-même.
Martin Smith

2
Les statistiques sont créées par une fonction d'agrégation interne uniquement ( StatMan) qui génère un blob (ironiquement, ce nom est mis en surbrillance en tant que fonction dans une fenêtre de requête SSMS). Logiquement, les statistiques sont associées à un index ou à un ensemble de colonnes de table, donc je commencerais par examiner les tables de métadonnées internes à la recherche d'une colonne binaryou varbinaryqui mènera au blob. Cela devrait être visible en utilisant DBCC PAGE, mais probablement pas autrement, car tout est interne.
Jon Seigel

1
@ivanmp J'ai édité votre question pour plus de clarté car la plupart des DBA les plus novices ne sauront pas ce qu'est un BP ou un QO.
Max Vernon

2
Autrefois, sysindexes.statblobmais depuis 2005, il revient NULLet l'emplacement est complètement non documenté, uniquement récupérable (à ma connaissance) via DBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;.
Aaron Bertrand

1
Trouvé les statistiques d'index - elles sont sys.sysidxstats- il semble qu'il y ait un pointeur LOB dans cette table. Je ne sais pas encore où sont les statistiques de la colonne; ils pourraient être dans ce tableau ainsi qu'il y a une typecolonne.
Jon Seigel

Réponses:


30

Je les ai trouvés.

  1. Créez une table avec un simple objet stats.

    CREATE DATABASE splunge;
    GO
    USE splunge;
    GO
    CREATE TABLE dbo.foo(bar INT, munge INT);
    GO
    CREATE STATISTICS x ON dbo.foo(bar);
    CREATE STATISTICS y ON dbo.foo(munge);
    GO
    INSERT dbo.foo SELECT s1.[object_id], s2.[object_id]
      FROM sys.objects AS s1
      CROSS JOIN sys.objects AS s2;
    GO
    UPDATE STATISTICS dbo.foo;
    GO
  2. Connectez-vous à l'aide du DAC ( ADMIN:Server[\instance]).

  3. Exécutez les requêtes suivantes:

    DBCC SHOW_STATISTICS('dbo.foo', 'x') WITH STATS_STREAM;
    DBCC SHOW_STATISTICS('dbo.foo', 'y') WITH STATS_STREAM;
    
    SELECT name, imageval 
      FROM sys.stats AS s
      INNER JOIN sys.sysobjvalues AS o
      ON s.object_id = o.objid
      AND s.stats_id = o.subobjid
    WHERE 
      s.object_id = OBJECT_ID('dbo.foo');

Vous remarquerez que imagevalpour chaque objet stats, ce n'est pas la même chose que le blob stats, mais il contient le blob stats - il est juste décalé. Sur mon système, cela a produit ceci pour x (j'ai évidemment tronqué pas mal de bits):

0x0100...bunch of chars...000007000000C4E1BE00EEA0...rest the same
                            0x07000000C4E1BE00EEA0...rest the same

Et cela pour y:

0x0100...bunch of chars...430007000000C7E1BE00EEA0...rest the same
                            0x07000000C7E1BE00EEA0...rest the same

Il en va de même pour les statistiques indexées.

Vous pourriez probablement faire une validation supplémentaire de cela avec une série de requêtes à l'aide de DBCCcommandes. Tout d'abord, recherchez les pages concernées par l'index clusterisé sys.sysobjvalues(remplacez le nom de votre base de données):

DBCC IND('splunge', 'sys.sysobjvalues', 1);

Le résultat listera un tas de pages, celles qui vous intéressent PageType = 1. Avec une nouvelle base de données, vous devriez pouvoir trouver ces informations sur l'une des pages avec les PagePIDvaleurs les plus élevées. Par exemple, sur mon système, c'était la page 281, alors j'ai regardé de plus près cette page:

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

DBCC PAGE(@dbid, 1, 281, 3);

DBCC TRACEOFF(3604);

Effectivement, j'ai trouvé les données dans l'emplacement 17:

Résultats partiels de la page DBCC

(Sur des bases de données plus grandes, vous devrez peut-être faire beaucoup plus de chasse et de picage, car il n'y a aucune garantie que même un nouvel objet de statistiques se retrouvera sur une nouvelle (er) page.)

Allez-y et essayez ceci à la maison, mais il y a une raison pour laquelle vous devez vous connecter avec le DAC pour cela. Je serais curieux de savoir, bien sûr, ce que vous allez faire de ces informations que vous ne pourriez pas faire avec la DBCC SHOW_STATISTICSsortie.

Notez que cela n'essaie bien sûr pas de décoder le STATS_STREAMpour fournir un histogramme ou d'autres informations, et je n'ai trouvé aucune preuve que la sortie tabulaire de DBCC SHOW_STATISTICS ... WITH HISTOGRAMest stockée n'importe où au format tableau. Joe Chang a des informations sur le décodage si c'est ce que vous recherchez. Je ne pense pas que ce soit quelque chose que vous voudriez faire dans une requête - utilisez simplement DBCC.


2
Nous avons un gagnant mesdames et messieurs. Je vous lève mon chapeau monsieur.
Zane

Hahaha, félicitations et merci, monsieur! Ne vous inquiétez pas, je ne fais rien que je ne devrais pas faire (AKA "stupide"). C'est juste pour la croissance personnelle. Je m'y suis vraiment intéressé une fois que j'ai réalisé que je ne pouvais rien trouver à ce sujet nulle part. =)
ivanmp

À propos de l'article de Joe Chang, je l'ai trouvé pendant que je cherchais la réponse à cela. J'avais déjà commencé à le lire. Merci encore. :)
ivanmp
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.