查sql server数据库分区大小须关联sys.allocation_units与sys.database_files,因sys.partitions无磁盘占用信息,而sys.allocation_units的used_pages×8192才得实际字节数,且需绑定文件组以区分多文件场景。

SQL Server里查数据库分区大小,不能只看sys.partitions
直接对sys.partitions的rows或data_compression_desc做聚合,得不到实际磁盘占用。这个视图只管行数和压缩类型,不存页数或字节数。真正要算大小,得顺藤摸瓜到sys.allocation_units——它记录了每个分配单元(IN_ROW_DATA、LOB_DATA、ROW_OVERFLOW_DATA)占了多少页。
为什么必须关联sys.allocation_units和sys.database_files
单靠sys.allocation_units.total_pages还是不行:它给的是总页数,但没说明这些页落在哪个物理文件上。如果一个数据库跨多个.mdf/.ndf文件,或者开了文件组+分区方案,不绑定sys.database_files就无法区分是哪个文件贡献的容量。更关键的是,total_pages包含已分配但未使用的页(比如空间预分配),真实数据大小得用used_pages来算。
-
used_pages≈ 实际写入数据的页数(含索引页、IAM页等) -
data_pages才是纯数据行占用的页(不含索引页),但多数场景用used_pages更贴近“分区实际开销” - 每页固定 8KB,所以最终字节数 =
used_pages * 8192
完整查询示例:按数据库 + 分区方案 + 文件组统计大小
下面这段 SQL 在master上下文执行,遍历所有用户数据库,汇总每个数据库下各分区方案(或NULL表示未分区)在各文件组中的used_pages总和:
SELECT DB_NAME() AS database_name, ISNULL(pf.name, 'NOT_PARTITIONED') AS partition_scheme, fg.name AS filegroup_name, SUM(a.used_pages) * 8192 AS total_bytes FROM sys.partitions p JOIN sys.allocation_units a ON p.partition_id = a.container_id JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id JOIN sys.data_spaces ds ON i.data_space_id = ds.data_space_id LEFT JOIN sys.partition_schemes pf ON ds.data_space_id = pf.data_space_id LEFT JOIN sys.filegroups fg ON ds.data_space_id = fg.data_space_id WHERE p.index_id IN (0, 1) -- 堆或聚集索引(跳过非聚集索引避免重复计) GROUP BY pf.name, fg.name;
注意:container_id在sys.allocation_units中对应partition_id(堆/索引)或hobt_id(LOB段),这里只处理常规分区表;若需包含LOB列,还得额外JOIN sys.partitions on hobt_id。
容易被忽略的边界情况
分区表的统计不是“开箱即用”,几个硬坑得手动绕开:
- 系统数据库(
master,model,msdb,tempdb)默认不参与分区,但脚本若没加AND database_id > 4过滤,tempdb的临时对象可能污染结果 -
sys.allocation_units.type = 2(LOB_DATA)和type = 3(ROW_OVERFLOW_DATA)的页,container_id指向hobt_id而非partition_id,强行ONp.partition_id = a.container_id会漏掉大字段实际开销 - 压缩后的
used_pages已反映压缩效果,但data_compression_desc字段在sys.partitions里,需要额外LEFT JOIN才能标出哪些分区启用了PAGE或ROW压缩
真要精确到每个分区函数边界(比如按$PARTITION.myfunc(col)分片统计),就得动态拼SQL跑每个库,用DBCC SHOWFILESTATS或sys.dm_db_file_space_usage补位——那已经超出单纯聚合系统表的范畴了。










