複数のファイルのファイルグループに割り当て単位を含む正確なファイルを特定する方法はありますか?


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_allocations、SQL Server 2012で導入された文書化されていない動的管理機能(DMF)にあるAllocationUnitIDとFileIDの関連付けを設定します(2012より前のバージョンの場合、この情報を取得できますDBCC IND())。そのローカル一時テーブルは、元のクエリの修正バージョンに結合されます。

データベースのサイズによっては、そのデータを取得するのに数秒以上かかることがあるため、そのDMFからのデータはパフォーマンスのために一時テーブルに配置されます。DISTINCTDMFは、データ・ページごとに1つの行を返すことがあるため、キーワードが使用され、各割当単位ごとに複数のデータ・ページがあります。

私は左に参加し、0のデータ・ページ(典型的には、元のクエリが返す割当単位ので、元のクエリにデータROW_OVERFLOW_DATA及びLOB_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列がインデックスの合計ページであることを指摘したいと思います。結果がインデックスごとに複数の行を返す場合、インデックスは複数のファイルに分散されますが、各ファイルのインデックスの量は表示されません。各行には、ファイルごとではなく、インデックスごとの合計ページ数が表示されます。(私は私のインデックスを冷却する、と思った私はそれを実行した最初の数回は完全にファイル間でバランスされている、私が間違っていた
ジェームズ・ジェンキンス

1

Remus Rusanuは2013年5月21日にこの質問に対する回答を提供しました。

1つのファイルグループ、複数のデータファイル、各ファイルのテーブルのリストを取得する方法

彼の反応は:

ファイルグループ内のオブジェクトは、ファイルグループ内のすべてのデータファイルを使用します。FG1のすべてのテーブルは、Datafile1、Datafile2、およびDatafile3に等しく存在します。配置を制御する必要がある場合は、個別のファイルグループを作成する必要があります。


ありがとう。私は本当にそれがどこに行くかをコントロールしたくはありませんが、むしろどこに行ったのかを見たいです。
-swasheck

3
参考までに、これはすべてのファイルが同時に作成されたと仮定すると正しいです。ファイルがファイルグループに追加された場合、または他のトレースフラグが使用された場合、すべてのファイルに含まれているとは限りません。彼が間違っている言っているのではなく、それが依存している言っているからです :)
ショーンはサラチップスを削除する
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.