¿Existe alguna forma de determinar el archivo exacto que contiene una unidad de asignación en un grupo de archivos de múltiples archivos?

13

Esperaba obtener una vista granular de qué archivos de base de datos contenían qué unidades de asignación para los diversos HoBT (tanto alineados como no alineados) que viven en una base de datos.

La consulta que siempre he usado (ver más abajo) me ha servido bien hasta que comenzamos a crear múltiples archivos de datos por grupo de archivos y solo soy capaz de descubrir cómo llegar a ser tan granular como el nivel de grupo de archivos.

select 
    SchemaName = sh.name, 
    TableName = t.name, 
    IndexName = i.name, 
    PartitionNumber = p.partition_number,
    IndexID = i.index_id,
    IndexDataspaceID = i.data_space_id,
    AllocUnitDataspaceID = au.data_space_id,
    PartitionRows = p.rows
from sys.allocation_units au
join sys.partitions p
    on au.container_id = p.partition_id
join sys.indexes i 
    on i.object_id = p.object_id
    and i.index_id = p.index_id
join sys.tables t 
    on p.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
where sh.name != 'sys'
    and au.type = 2
union all 
select 
    sh.name, 
    t.name, 
    i.name, 
    p.partition_number,
    i.index_id,
    i.data_space_id,
    au.data_space_id,
    p.rows
from sys.allocation_units au
join sys.partitions p
    on au.container_id = p.hobt_id
join sys.indexes i 
    on i.object_id = p.object_id
    and i.index_id = p.index_id
join sys.tables t 
    on p.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
where sh.name != 'sys'
    and au.type in (1,3)
order by t.name, i.index_id,p.partition_number;

Sin embargo, esta consulta no funcionará cuando haya varios archivos en un grupo de archivos, ya que solo puedo llegar a relacionar una unidad de asignación con un espacio de datos y, en última instancia, un grupo de archivos. Me gustaría saber si me falta otro DMV o catálogo que pueda usar para identificar más a fondo qué archivo del grupo de archivos contiene una unidad de asignación.

La pregunta detrás de esta pregunta es que estoy tratando de evaluar los efectos reales de comprimir estructuras particionadas. Sé que puedo hacer un uso de antes y después FILEPROPERTY(FileName,'SpaceUsed')para el archivo y un antes y después sys.allocation_units.used_pages/128.para obtener esta información, pero el ejercicio en sí mismo me hizo preguntarme si podría identificar el archivo específico que contiene una unidad de asignación específica.

He estado jugando con %%physloc%%la esperanza de que pueda ayudar, pero no me da lo que estoy buscando. Los siguientes enlaces fueron proporcionados por Aaron Bertrand :

swasheck
fuente

Respuestas:

11

Prueba la siguiente consulta. Primero crea una tabla temporal local y luego la completa con las asociaciones AllocationUnitID-to-FileID que se encuentran en sys.dm_db_database_page_allocationsuna Función de administración dinámica (DMF) no documentada introducida en SQL Server 2012 (para versiones anteriores a 2012, puede obtener esta información DBCC IND()). Esa tabla temporal local se UNE a una versión modificada de la consulta original.

Los datos de ese DMF se colocan en una tabla temporal para el rendimiento ya que, dependiendo del tamaño de la base de datos, puede tomar más de unos segundos obtener esos datos. La DISTINCTpalabra clave se usa porque ese DMF devuelve una fila por página de datos, y hay varias páginas de datos por cada unidad de asignación.

Me uní a la izquierda de esos datos en la consulta original ya que la consulta original devuelve unidades de asignación que tienen 0 páginas de datos (típicamente ROW_OVERFLOW_DATAy LOB_DATAtipos). También agregué el total_pagescampo para que sea más fácil relacionar ese punto de datos con las filas que tienen NULLs para los archivos de datos. Si no le importan las Unidades de asignación que tienen 0 filas, entonces estaría bien cambiar eso LEFT JOINpara que sea ​​un INNER JOIN.

IF (OBJECT_ID(N'tempdb..#AllocationsToFiles') IS NULL)
BEGIN
    -- DROP TABLE #AllocationsToFiles;
    CREATE TABLE #AllocationsToFiles
    (
      ObjectID INT NOT NULL,
      IndexID INT NOT NULL,
      PartitionID INT NOT NULL,
      RowsetID BIGINT NOT NULL,
      AllocationUnitID BIGINT NOT NULL,
      AllocatedPageFileID SMALLINT NOT NULL
    );
END;

IF (NOT EXISTS(SELECT * FROM #AllocationsToFiles))
BEGIN
  --TRUNCATE TABLE #AllocationsToFiles;
  INSERT INTO #AllocationsToFiles (ObjectID, IndexID, PartitionID, RowsetID,
                                   AllocationUnitID, AllocatedPageFileID)
    SELECT DISTINCT alloc.[object_id], alloc.[index_id], alloc.[partition_id],
           alloc.[rowset_id], alloc.[allocation_unit_id], alloc.[allocated_page_file_id]
    FROM   sys.dm_db_database_page_allocations(DB_ID(), NULL, NULL, NULL,
                                               'LIMITED') alloc
    WHERE  alloc.is_allocated = 1
    AND    alloc.is_iam_page = 0;
END;

SELECT
    SchemaName = sh.name, 
    TableName = t.name, 
    IndexName = i.name, 
    PartitionNumber = p.partition_number,
    IndexID = i.index_id,
    IndexDataspaceID = i.data_space_id,
    AllocUnitDataspaceID = au.data_space_id,
    PartitionRows = p.[rows],
    TotalPages = au.total_pages,
    AllocationUnitType = au.type_desc,
    LogicalFileName = dbf.[name],
    PhysicalFileName = dbf.[physical_name]
    --,p.[object_id], p.[partition_id], au.allocation_unit_id
FROM sys.allocation_units au
INNER JOIN sys.partitions p
        ON au.container_id = IIF(au.[type] = 2, p.[partition_id], p.[hobt_id])
INNER JOIN sys.indexes i 
        ON i.[object_id] = p.[object_id]
       AND i.index_id = p.index_id
INNER JOIN sys.tables t 
        ON p.[object_id] = t.[object_id]
INNER JOIN sys.schemas sh
        ON t.[schema_id] = sh.[schema_id]
LEFT JOIN (#AllocationsToFiles alloc
       INNER JOIN sys.database_files dbf
               ON dbf.[file_id] = alloc.AllocatedPageFileID
          ) 
        ON alloc.ObjectID = p.[object_id]
       AND alloc.IndexID = p.index_id
       AND alloc.PartitionID = p.partition_number
       AND alloc.AllocationUnitID = au.allocation_unit_id
WHERE sh.name <> N'sys'
ORDER BY t.name, i.index_id, p.partition_number;
Solomon Rutzky
fuente
Esta es una gran herramienta, gracias. Quiero señalar que la columna TotalPages es páginas totales para el índice. Cuando los resultados devuelven varias filas por índice, el índice se distribuye entre varios archivos, pero no muestra la cantidad del índice en cada archivo. Cada fila mostrará el número total de páginas por índice, no por archivo. ( Las primeras veces que lo ejecuté pensé, genial, mis índices están perfectamente equilibrados en todos los archivos, me equivoqué )
James Jenkins
1

Remus Rusanu, el 21 de mayo de 2013, respondió a esta pregunta:

Un grupo de archivos, múltiples archivos de datos, cómo obtener una lista de tablas en cada archivo

Su respuesta fue:

Un objeto en un grupo de archivos usará todos los archivos de datos en el grupo de archivos. Cualquier tabla en FG1 reside igualmente en Datafile1, Datafile2 y Datafile3. Si necesita controlar la ubicación, debe crear grupos de archivos distintos.

RLF
fuente
Gracias. Realmente no quiero controlar a dónde va, sino ver a dónde se fue.
swasheck
3
FYI: esto es correcto asumiendo que todos los archivos se crearon al mismo tiempo. Si se agregaron archivos al grupo de archivos u otros indicadores de rastreo, es posible que no esté en todos los archivos. No digo que está equivocado, porque no lo está, diciendo que depende :)
Sean Gallardy