データベースに存在するさまざまな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 によって提供されました:
次のクエリを試してください。最初にローカル一時テーブルを作成し、次に、SQL Server 2012で導入された、ドキュメント化されていない動的管理関数(DMF)である_sys.dm_db_database_page_allocations
_にあるAllocationUnitIDとFileIDの関連付けを設定します(2012より前のバージョンでは、 DBCC IND()
)からのこの情報。そのローカル一時テーブルは、元のクエリの変更されたバージョンに結合されます。
データベースのサイズによっては、そのデータを取得するのに数秒以上かかる可能性があるため、そのDMFからのデータはパフォーマンスのために一時テーブルに配置されます。 DMFはデータページごとに1行を返し、各アロケーションユニットごとに複数のデータページがあるため、DISTINCT
キーワードが使用されます。
元のクエリはデータページが0のアロケーションユニット(通常は_ROW_OVERFLOW_DATA
_および_LOB_DATA
_タイプ)を返すため、そのデータを元のクエリに結合しました。また、_total_pages
_フィールドを追加して、そのデータポイントをデータファイルのNULL
sを持つ行に簡単に関連付けることができるようにしました。行が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;
_
2013年5月21日のRemus Rusanuは、この質問に対する回答を提供しました。
1つのファイルグループ、複数のデータファイル、各ファイルのテーブルのリストを取得する方法
彼の反応は:
ファイルグループ内のオブジェクトは、ファイルグループ内のすべてのデータファイルを使用します。 FG1内のすべてのテーブルは、Datafile1、Datafile2、およびDatafile3に等しく存在します。配置を制御する必要がある場合は、個別のファイルグループを作成する必要があります。