여러 파일의 파일 그룹에 할당 단위를 포함하는 정확한 파일을 결정하는 방법이 있습니까?


13

데이터베이스에있는 다양한 HoBT (정렬 및 비 정렬)에 대한 할당 단위를 포함하는 데이터베이스 파일에 대한 세부 정보를 얻고 싶었습니다.

항상 사용했던 쿼리 (아래 참조)는 파일 그룹당 여러 데이터 파일을 만들기 시작할 때까지 잘 작동했으며 파일 그룹 수준만큼 세분화하는 방법 만 알아낼 수있었습니다.

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;

그러나 할당 단위를 데이터 공간과 궁극적으로 파일 그룹과 관련시킬 수 있기 때문에 파일 그룹에 여러 파일이 있으면이 쿼리가 작동하지 않습니다. 파일 그룹에서 어떤 파일이 할당 단위를 포함하는지 더 자세히 식별하는 데 사용할 수있는 다른 DMV 또는 카탈로그가 있는지 알고 싶습니다.

이 질문의 뒤에 질문은 파티션 구조를 압축하는 실제 효과를 평가하려고한다는 것입니다. 이 정보를 얻기 위해 FILEPROPERTY(FileName,'SpaceUsed')파일에 전후 사용 을 할 수 있다는 것을 알고 sys.allocation_units.used_pages/128.있지만 연습 자체로 인해 특정 할당 단위가 포함 된 특정 파일을 식별 할 수 있는지 궁금해했습니다.

나는 %%physloc%%그것이 도움이 될 수 있기를 희망하면서 엉망이되었지만 , 내가 찾고있는 것을 얻지 못합니다. 아래 링크는 Aaron Bertrand 가 제공 한 것입니다 .


답변:


11

다음 쿼리를 시도하십시오. 먼저 로컬 임시 테이블을 만든 다음 sys.dm_db_database_page_allocationsSQL Server 2012에 도입 된 문서화되지 않은 DMF (Dynamic Management Function)에 있는 AllocationUnitID-FileID 연결로 채 웁니다 (2012 이전 버전의 경우이 정보를 얻을 수 있음 DBCC IND()). 그런 다음 해당 로컬 임시 테이블은 원래 쿼리의 수정 된 버전으로 결합됩니다.

데이터베이스의 크기에 따라 해당 데이터를 가져 오는 데 몇 초 이상 걸릴 수 있으므로 해당 DMF의 데이터는 성능을 위해 임시 테이블에 배치됩니다. DISTINCTDMF는 데이터 페이지 당 하나 개의 행을 반환하기 때문에 키워드가 사용되며, 각 할당 단위에 여러 데이터 페이지가있다.

나는 왼쪽 합류 0 데이터 페이지 (일반적으로 가지고있는 원래의 쿼리를 반환 할당 단위부터 원래의 질의에 데이터 ROW_OVERFLOW_DATALOB_DATA유형). 또한 total_pages해당 데이터 포인트를 NULL데이터 파일의 행과 더 쉽게 연관시킬 수 있도록 필드를 추가했습니다 . 행이 0 인 할당 단위를 신경 쓰지 않으면이를로 변경하는 LEFT JOIN것이 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;

이것은 훌륭한 도구입니다. 감사합니다. TotalPages 열이 인덱스의 총 페이지임을 지적하고 싶습니다. 결과가 인덱스 당 여러 행을 반환하면 인덱스는 여러 파일에 분산되지만 각 파일에 얼마나 많은 인덱스가 있는지는 보여주지 않습니다. 각 행에는 파일이 아닌 인덱스 당 총 페이지 수가 표시됩니다. ( 내가 처음 몇 번이나 실행했을 때, 내 색인이 파일간에 완벽하게 균형을 잡았다 고 생각했다. )
James Jenkins

1

2013 년 5 월 21 일 Remus Rusanu는이 질문에 대한 답변을 제공했습니다.

하나의 파일 그룹, 여러 데이터 파일, 각 파일에서 테이블 목록을 얻는 방법

그의 답변은 다음과 같습니다.

파일 그룹의 객체는 파일 그룹의 모든 데이터 파일을 사용합니다. FG1의 모든 테이블은 Datafile1, Datafile2 및 Datafile3에 동일하게 상주합니다. 배치를 제어해야하는 경우 고유 한 파일 그룹을 만들어야합니다.


감사. 나는 그것이 어디로 가는지를 실제로 통제하고 싶지 않고 오히려 어디로 갔는지를보고 싶다.
swasheck

3
참고로-모든 파일이 동시에 생성되었다고 가정하면 정확합니다. 파일이 파일 그룹에 추가되었거나 다른 추적 플래그가 사용 된 경우 모든 파일에 있지 않을 수 있습니다. 그가 틀 렸기 때문에 그가 틀렸다고 말하지 않고, 그것이 달려 있다고 말하는 것 :)
Sean Gallardy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.