Wo werden Statistiken in SQL Server physisch gespeichert?

27

Wo werden die vom Abfrageoptimierungsprogramm verwendeten Statistiken physisch in einer SQL Server-Datenbankdatei und im Pufferpool gespeichert?

Gibt es eine Möglichkeit, die von Statistiken verwendeten Seiten mithilfe von DMVs und / oder DBCC herauszufinden?

Ich besitze sowohl SQL Server 2008-Interna als auch SQL Server-Interna und Fehlerbehebungsbücher. In keinem dieser Bücher geht es um die physische Struktur der Statistiken. Andernfalls kann ich diese Informationen nicht finden.

ivanmp
quelle
1
Wenn Sie eine reine Statistikkopie der Datenbank erstellen, wird eine Binärdatei STATS_STREAMangezeigt, in der ich noch nie nachgesehen habe, ob dies in der Datei selbst auffindbar ist.
Martin Smith
2
Statistiken werden von einer nur internen Aggregatfunktion ( StatMan) erstellt, die einen Blob ausgibt (ironischerweise wird dieser Name als Funktion in einem SSMS-Abfragefenster hervorgehoben). Logischerweise sind Statistiken mit einem Index oder einer Reihe von Tabellenspalten verknüpft, daher würde ich zunächst die internen Metadatentabellen auf eine binaryoder eine varbinarySpalte untersuchen, die zum Blob führt. Dies sollte mit sichtbar sein DBCC PAGE, aber wahrscheinlich nicht anders, weil es alles intern ist.
Jon Seigel
1
@ivanmp Ich habe Ihre Frage aus Gründen der Klarheit bearbeitet, da viele der unerfahrenen Datenbankadministratoren nicht wissen, was ein BP oder ein QO ist.
Max Vernon
2
Früher war es in, sysindexes.statblobaber seit 2005 kehrt es zurück NULLund der Ort ist komplett undokumentiert, nur abrufbar (das weiß ich) durch DBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;.
Aaron Bertrand
1
Haben die Index-Statistiken gefunden - sie befinden sich in sys.sysidxstats- es sieht so aus, als ob sich in dieser Tabelle ein LOB-Zeiger befindet. Ich bin mir noch nicht sicher, wo die Spaltenstatistiken sind. Sie könnten in dieser Tabelle stehen, genauso wie es eine typeSpalte gibt.
Jon Seigel

Antworten:

30

Fand sie.

  1. Erstellen Sie eine Tabelle mit einem einfachen Statistikobjekt.

    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. Stellen Sie eine Verbindung mit dem DAC ( ADMIN:Server[\instance]) her.

  3. Führen Sie die folgenden Abfragen aus:

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

Sie werden feststellen, dass imagevalfür jedes Statistikobjekt nicht dasselbe gilt wie für das Statistik-Blob, es enthält jedoch das Statistik-Blob - es ist lediglich ein Versatz. Auf meinem System ergab sich folgendes für x (ich habe offensichtlich einiges abgeschnitten):

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

Und das für Sie:

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

Gleiches gilt für indexbasierte Statistiken.

Sie könnten dies wahrscheinlich mit einer Reihe von Abfragen unter Verwendung von DBCCBefehlen überprüfen. Ermitteln Sie zunächst die Seiten, die am Clustered-Index beteiligt sind sys.sysobjvalues(ersetzen Sie Ihren Datenbanknamen):

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

Das Ergebnis enthält eine Reihe von Seiten, an denen Sie interessiert sind PageType = 1. Mit einer neuen Datenbank sollten Sie diese Informationen auf einer der Seiten mit den höchsten PagePIDWerten finden. Auf meinem System war dies beispielsweise Seite 281, also habe ich mir diese Seite genauer angesehen:

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

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

DBCC TRACEOFF(3604);

Natürlich habe ich die Daten in Slot 17 gefunden:

Teilergebnisse der DBCC

(Bei größeren Datenbanken müssen Sie möglicherweise viel mehr suchen und picken, da nicht garantiert werden kann, dass auch ein neues Statistikobjekt auf einer neuen (er) Seite angezeigt wird.)

Probieren Sie dies zu Hause aus, aber es gibt einen Grund, warum Sie sich dafür mit dem DAC verbinden müssen. Ich wäre natürlich gespannt, was Sie mit diesen Informationen machen werden, die Sie mit der DBCC SHOW_STATISTICSAusgabe nicht machen könnten .

Beachten Sie, dass dies natürlich nicht versucht, das STATS_STREAMHistogramm oder andere Informationen zu dekodieren , und ich konnte keine Beweise dafür finden, dass die tabellarische Ausgabe von DBCC SHOW_STATISTICS ... WITH HISTOGRAMirgendwo im Tabellenformat gespeichert ist. Joe Chang hat einige Informationen zum Dekodieren, wenn Sie danach suchen. Ich glaube nicht, dass Sie das in einer Abfrage tun möchten - verwenden Sie einfach DBCC.

Aaron Bertrand
quelle
2
Wir haben einen Gewinner, meine Damen und Herren. Ich tippe meinen Hut auf Sie, Sir.
Zane
Hahaha, herzlichen Glückwunsch und vielen Dank, Sir! Keine Sorge, ich tue nichts, was ich nicht tun sollte (AKA "dumm"). Es ist nur für persönliches Wachstum. Ich habe mich sehr dafür interessiert, als ich merkte, dass ich nirgendwo etwas darüber finden konnte. =)
ivanmp
Über Joe Changs Artikel fand ich es, als ich nach der Antwort darauf suchte. Ich hatte bereits angefangen, es zu lesen. Danke noch einmal. :)
ivanmp