向文件组中的文件报告空间消耗 - 如何对跨文件传播数据的算法进行逆向工程

Alo*_*yte 5 performance monitoring sql-server dmv disk-space performance-tuning

我想知道如何计算文件组中每个文件消耗的数据分布,回到存储它的索引(HEAP、CLUSTERED、NONCLUSTERED)。我的目的是定义哪些 I/O 去磁盘上的哪个位置。

data_space_id从 开始sys.indexes,显示已使用、已分配的页面;和data_space_id大小从sys.filegroups. 所以我到达了用于将数据存储到文件组内的文件的加权(按可用空间比率?)算法生效的地方。我可以加入sys.database_files使用data_space_id.

sys.dm_allocation_units (通过object_Id和连接到索引index_Id)我得到partition_ID;加入sys.dm_partitions建议行数,使用和分配的页面,允许计算也显示每个分区的可用内容。无法分区到文件...?

我有一个查询,我根据文件组中每个文件的已使用页面的比率将 DATA 分配给 FILE,将该比率应用于存储在文件所属的文件组上的索引数据。

是否有更好的方法将表/索引数据向下钻取到文件级分配?(测量而不是计算?)

对于 indid = 0 或 indid = 1,dpages 是使用的数据页数。
对于 indid > 1,dpages 是使用的索引页数。

对于 indid = 0 或 indid = 1,used 是用于所有索引和表数据的总页数。
对于 indid > 1,used 是用于索引的页数。

对于 indid = 0 或 indid = 1,reserved 是为所有索引和表数据分配的页数。
对于 indid > 1,reserved 是为索引分配的页数。

查询语句:

Select  T.Name TableName,
        ISNULL(SI.Name, SI.type_desc) IndexName, 
    SI.index_id, 
    SI.type_desc, 
    SI.data_space_id,
    S.rows Rows,
    S.rowmodctr,
    PIx.avg_fragmentation_in_percent,
    PIx.fragment_count,
    PIx.avg_fragment_size_in_pages,
    CASE SI.Index_ID
    WHEN 0 THEN S.dpages
    WHEN 1 THEN S.dpages
    END DataPages,
    CASE 
    WHEN SI.index_id > 1
        THEN S.dpages
    END IndexPages,
    FileUsageRatio,
    S.dpages*FileUsageRatio RationedDataPagesToFile,
    physical_name,
    CASE SI.Index_ID
    WHEN 0 THEN S.Used 
    WHEN 1 THEN S.Used
    END UsedTableDataPages,
    CASE 
    WHEN SI.index_id > 1
        THEN S.Used
    END UsedIndexPages,
    CASE SI.Index_ID
    WHEN 0 THEN S.reserved 
    WHEN 1 THEN S.reserved
    END ReservedTableDataPages,
    CASE 
    WHEN SI.index_id > 1
        THEN S.Reserved
    END ReservedIndexPages,
    FG.name FileGroupName,
    FG_SpaceUsage.FG_AllocatePages,
    FG_SpaceUsage.FG_UsedPages,
    FG_SpaceUsage.FG_FreePages,
    FG.type_desc FileGroup_Type_desc,
    OIx.singleton_lookup_count,
    OIx.range_scan_count,
    OIx.page_io_latch_wait_count,
    OIx.page_io_latch_wait_in_ms,
    OIx.page_latch_wait_count,
    OIx.page_latch_wait_in_ms,
    OIx.row_lock_count,
    OIx.row_lock_wait_count,
    OIx.row_lock_wait_in_ms,
    OIx.page_lock_count,
    OIx.page_lock_wait_count,
    OIx.page_lock_wait_in_ms
from SYS.tables T
JOIN sys.indexes SI
ON T.Object_ID = SI.Object_ID
JOIN sys.filegroups FG
ON FG.Data_Space_ID = SI.Data_Space_ID
JOIN sys.partitions P
ON P.index_id = SI.index_id
AND P.object_id = SI.object_id
JOIN sys.allocation_units AU
ON AU.allocation_unit_id = P.partition_id
JOIN sys.dm_db_index_operational_stats(db_id(),NULL,NULL,NULL) OIx
ON OIx.index_id = P.index_id
AND OIx.object_id = P.object_id
JOIN sys.dm_db_index_physical_stats(db_id(),NULL,NULL,NULL,NULL) PIx
ON PIx.index_id = P.index_id
AND PIx.object_id = P.object_id
JOIN sys.sysindexes S
ON S.IndID = SI.Index_ID
AND S.ID = SI.Object_ID
JOIN (
SELECT Data_Space_ID, SUM(SIZE) FG_AllocatePages, SUM(UsedPages) FG_UsedPages,   SUM   (SIZE) - SUM(UsedPages) FG_FreePages
FROM SYS.database_files DBF
    CROSS APPLY (   SELECT FILEPROPERTY(DBF.name, 'SpaceUsed') AS UsedPages) PagesUsed
GROUP BY DBF.data_space_id
) FG_SpaceUsage
ON FG_SpaceUsage.data_space_id = FG.data_space_id
JOIN 
(
 SELECT CTE.data_space_id, CTE.file_ID, CTE.physical_name,      CTE.UsedPages*1.0/AGGREGATED.Total_UsedPages FileUsageRatio
 FROM (
 SELECT data_space_Id, File_ID, Physical_Name, Size, PagesUsed.UsedPages, Size-     PagesUsed.UsedPages FreePages
 FROM sys.database_Files DBF
 CROSS APPLY (  SELECT FILEPROPERTY(DBF.name, 'SpaceUsed') AS UsedPages) PagesUsed
 ) CTE
JOIN
    (SELECT Data_Space_ID, SUM(UsedPages) Total_UsedPages
     FROM (
            SELECT data_space_Id, File_ID, Physical_Name, Size, PagesUsed.UsedPages, Size-PagesUsed.UsedPages FreePages
            FROM sys.database_Files DBF
            CROSS APPLY (   SELECT FILEPROPERTY(DBF.name, 'SpaceUsed') AS UsedPages) PagesUsed
            ) CTE
     GROUP BY Data_Space_ID
     ) AGGREGATED
ON CTE.data_space_id = AGGREGATED.data_space_id
) DataUsageRatio
ON DataUsageRatio.data_space_id = FG.data_space_id

ORDER BY TableName, Index_ID
Run Code Online (Sandbox Code Playgroud)

Alo*_*yte 2

经过深思熟虑,我做不到我想做的事,比我现在做的更好。SQL Server 不会存储比看起来更深的文件组级别的内容。从那里开始,一切都只是内部结构;并且没有公开的方法可供查看。

背景链接:

循环法与比例填充作者:Rob Nicholson
理解 -E 启动参数作者:James Rowland-Jones