¿Dónde se almacenan físicamente las estadísticas en SQL Server?


27

¿Dónde se almacenan físicamente las estadísticas utilizadas por el optimizador de consultas dentro de un archivo de base de datos de SQL Server y el grupo de búferes?

Más específicamente, ¿hay alguna forma de averiguar las páginas utilizadas por las estadísticas usando DMV y / o DBCC?

Poseo los libros internos de SQL Server 2008 y los internos de SQL Server y Solución de problemas y ninguno de ellos habla sobre la estructura física de las estadísticas; si lo hacen, no podré encontrar esta información.


1
Cuando crea una copia de la base de datos solo de estadísticas, muestra un STATS_STREAMarchivo binario que nunca he investigado si esto es algo que se puede encontrar en el archivo.
Martin Smith

2
Las estadísticas son creadas por una función agregada solo interna ( StatMan) que genera un blob (irónicamente, ese nombre se resalta como una función en una ventana de consulta SSMS). Lógicamente, las estadísticas están asociadas con un índice o un conjunto de columnas de tabla, por lo que comenzaría examinando las tablas de metadatos internos en busca de una columna binaryo varbinarycolumna que conduzca al blob. Esto debería ser visible usando DBCC PAGE, pero probablemente no de otra manera porque es todo interno.
Jon Seigel

1
@ivanmp Edité su pregunta para mayor claridad ya que muchos de los DBA más novatos no sabrán qué es un BP o un QO.
Max Vernon

2
Solía ​​estar en, sysindexes.statblobpero desde 2005 eso regresa NULLy la ubicación está completamente indocumentada, solo recuperable (que yo sepa) a través DBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;.
Aaron Bertrand

1
Encontró las estadísticas del índice, están en sys.sysidxstats, parece que hay un puntero LOB en esa tabla. Todavía no estoy seguro de dónde están las estadísticas de la columna; podrían estar en esa mesa y hay una typecolumna.
Jon Seigel

Respuestas:


30

Los encontré.

  1. Crea una tabla con un simple objeto de estadísticas.

    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. Conéctese utilizando el DAC ( ADMIN:Server[\instance]).

  3. Ejecute las siguientes consultas:

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

Notarás que imagevalpara cada objeto de estadísticas no es lo mismo que el blob de estadísticas, pero contiene el blob de estadísticas, es solo un desplazamiento. En mi sistema produjo esto para x (obviamente he truncado un poco de bits):

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

Y esto para ti:

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

Lo mismo era cierto para las estadísticas basadas en índices.

Probablemente podría hacer una mayor validación de esto con una serie de consultas utilizando DBCCcomandos. Primero, descubra las páginas que están involucradas con el índice agrupado en sys.sysobjvalues(sustituya el nombre de su base de datos):

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

El resultado enumerará un montón de páginas, en las que está interesado PageType = 1. Con una nueva base de datos, debería poder encontrar esta información en una de las páginas con los PagePIDvalores más altos. Por ejemplo, en mi sistema, esta era la página 281, así que miré más de cerca esa página:

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

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

DBCC TRACEOFF(3604);

Efectivamente, encontré los datos en la ranura 17:

Resultados parciales de la página DBCC

(En bases de datos más grandes, es posible que tenga que cazar y picotear mucho más, ya que no hay garantía de que incluso un nuevo objeto de estadísticas termine en una nueva página (er)).

Siga adelante e intente esto en casa, pero hay una razón por la que necesita conectarse con el DAC para esto. Me gustaría saber, por supuesto, qué harás con esta información que no podrías hacer con la DBCC SHOW_STATISTICSsalida.

Tenga en cuenta que esto, por supuesto, no intenta decodificar el STATS_STREAMpara proporcionar histograma u otra información, y no pude encontrar ninguna evidencia de que la salida tabular de DBCC SHOW_STATISTICS ... WITH HISTOGRAMse almacena en cualquier lugar en formato de tabla. Joe Chang tiene información sobre la decodificación si eso es lo que buscas. No creo que sea algo que quiera hacer en una consulta, solo use DBCC.


2
Tenemos un ganador, damas y caballeros. Me quito el sombrero ante usted, señor.
Zane

Jajaja, felicidades y gracias, señor! No se preocupe, no estoy haciendo nada que no debería (también conocido como "estúpido"). Es solo para el crecimiento personal. Me interesé mucho una vez que me di cuenta de que no podía encontrar nada sobre esto en ningún lado. =)
ivanmp

Sobre el artículo de Joe Chang, lo encontré mientras buscaba la respuesta a esto. Ya había empezado a leerlo. Gracias de nuevo. :)
ivanmp
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.