Gdzie są fizycznie przechowywane statystyki w SQL Server?

27

Gdzie statystyki używane przez Optymalizator zapytań są fizycznie przechowywane w pliku bazy danych SQL Server i puli buforów?

Mówiąc dokładniej, czy istnieje sposób, aby dowiedzieć się, które strony są wykorzystywane przez statystyki przy użyciu DMV i / lub DBCC?

Jestem właścicielem zarówno SQL Server 2008 Internals, jak i SQL Server Wewnętrznych i książek o rozwiązywaniu problemów i żadna z nich nie mówi o fizycznej strukturze statystyk; jeśli tak, nie będę w stanie znaleźć tych informacji.

ivanmp
źródło
1
Kiedy tworzysz kopię bazy danych zawierającą tylko statystyki, pokazuje ona plik binarny, STATS_STREAMktórego nigdy nie analizowałem, czy jest to coś, co można znaleźć w samym pliku.
Martin Smith
2
Statystyki są tworzone przez wewnętrzną funkcję agregującą ( StatMan), która generuje obiekt blob (jak na ironię, nazwa ta jest podświetlona jako funkcja w oknie zapytania SSMS). Logicznie statystyki są powiązane z indeksem lub zestawem kolumn tabeli, więc zacznę od zbadania wewnętrznych tabel metadanych w poszukiwaniu binarylub varbinarykolumny, która doprowadzi do obiektu blob. Powinno to być widoczne przy użyciu DBCC PAGE, ale prawdopodobnie nie w żaden inny sposób, ponieważ wszystko jest wewnętrzne.
Jon Seigel
1
@ivanmp Zredagowałem twoje pytanie dla jasności, ponieważ wielu nowicjuszy DBA nie będzie wiedziało, czym jest BP lub QO.
Max Vernon
2
Kiedyś był, sysindexes.statblobale od 2005 roku powraca, NULLa lokalizacja jest całkowicie nieudokumentowana, można ją tylko odzyskać (o której wiem) DBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;.
Aaron Bertrand
1
Znaleziono statystyki indeksu - są w sys.sysidxstatsśrodku - wygląda na to, że w tej tabeli znajduje się wskaźnik LOB. Nie jestem pewien, gdzie są jeszcze statystyki kolumn; mogą być w tej tabeli, a także w typekolumnie.
Jon Seigel

Odpowiedzi:

30

Znalazłem ich.

  1. Utwórz tabelę z prostym obiektem statystyk.

    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. Połącz za pomocą DAC ( ADMIN:Server[\instance]).

  3. Uruchom następujące zapytania:

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

Zauważysz, że imagevaldla każdego obiektu statystyk nie jest to samo, co obiekt blob statystyki, ale zawiera on obiekt blob statystyki - jest po prostu przesunięty. W moim systemie uzyskałem to dla x (oczywiście skróciłem sporo bitów):

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

A to dla ciebie:

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

To samo dotyczy statystyk opartych na indeksach.

Prawdopodobnie można by to zrobić za pomocą szeregu zapytań za pomocą DBCCpoleceń. Najpierw dowiedz się, które strony są powiązane z indeksem klastrowym sys.sysobjvalues(zastąp nazwę bazy danych):

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

Wynik wyświetli listę stron, którymi jesteś zainteresowany PageType = 1. Dzięki nowej bazie danych powinieneś być w stanie znaleźć te informacje na jednej ze stron o najwyższych PagePIDwartościach. Np. W moim systemie była to strona 281, więc wtedy przyjrzałem się bliżej tej stronie:

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

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

DBCC TRACEOFF(3604);

Rzeczywiście, znalazłem dane w gnieździe 17:

Częściowe wyniki strony DBCC

(W większych bazach danych może być konieczne wykonanie znacznie więcej polowań i dziobania, ponieważ nie ma gwarancji, że nawet nowy obiekt statystyk znajdzie się na nowej (er) stronie).

Spróbuj tego w domu, ale jest powód, dla którego musisz połączyć się z DAC. Byłbym ciekawy, oczywiście, co zamierzasz zrobić z tymi informacjami, których nie możesz zrobić z danymi DBCC SHOW_STATISTICSwyjściowymi.

Zauważ, że to oczywiście nie próbuje dekodować w STATS_STREAMcelu dostarczenia histogramu lub innych informacji, i nie mogłem znaleźć żadnego dowodu, że wynik tabelaryczny DBCC SHOW_STATISTICS ... WITH HISTOGRAMjest przechowywany gdziekolwiek w formacie tabeli. Joe Chang ma pewne informacje na temat dekodowania, jeśli tego właśnie szukasz. Nie sądzę, żeby to było coś, co chciałbyś zrobić w zapytaniu - po prostu użyj DBCC.

Aaron Bertrand
źródło
2
Mamy zwycięzcę, panie i panowie. Daję ci kapelusz, proszę pana.
Zane
Hahaha, gratulacje i dzięki, proszę pana! Nie martw się, nie robię nic, czego nie powinienem (AKA „głupi”). To tylko dla osobistego rozwoju. Zainteresowałem się tym, gdy zdałem sobie sprawę, że nigdzie nie mogę o tym nic znaleźć. =)
ivanmp,
O artykule Joe Changa znalazłem go, gdy szukałem odpowiedzi na to pytanie. Już zacząłem go czytać. Dzięki jeszcze raz. :)
ivanmp