sys.database_files 和 SQL Server Management Studio 中的数据库属性对话框之间的可用空间不同

DrC*_*ste 3 sql-server ssms sql-server-2012

我现在看着这个几分钟,找不到提到这个的线程。

我想从 SQL Server 上的数据库查询当前使用的空间和可用空间。当我在 SQL Server Management Studio 中打开数据库上的属性对话框时,我查询的数字应该与我看到的数字相匹配,如下所示:

示例数据库属性显示大小:17689,00MB 和可用空间:16795,77MB

所以我浏览了一下,发现我可以sys.database_files像这样查询(从这里):

SELECT
        DB_NAME() AS DbName, 
        name AS FileName, 
        size/128.0 AS CurrentSizeMB, 
        size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT)/128.0 AS FreeSpaceMB 
    FROM sys.database_files; 
Run Code Online (Sandbox Code Playgroud)

这让我得到这个结果:

DbName 文件名 CurrentSizeMB FreeSpaceMB
数据库名称 数据库名称 17338.000000 16795.312500
数据库名 数据库名_日志 351.000000 331.234375

试图从上一个对话框中识别我的号码:

  • 好的,添加17338351让我达到17689对话框列出的大小
  • 但是对于可用空间,我找不到它,16795.312500几乎减少了半 MB

我该怎么做才能获得与属性对话框显示的可用空间完全相同的数字?

我是否以错误的方式使用了查询/公式,或者由于某些舍入(将页面/范围转换为 MB...),此时根本不可能?

Ran*_*gen 5

跟踪 ssms 使用的查询

一种方法是使用分析器的“调整”模板,然后跟踪您的登录信息

弹出这个查询

SELECT
(SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df WHERE df.type in ( 0, 2, 4 ) ) AS [DbSize],
(SUM(a.total_pages) + (SELECT ISNULL(SUM(CAST(df.size as bigint)), 0) FROM sys.database_files AS df WHERE df.type = 2 )) AS [SpaceUsed]
FROM
sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id left join sys.internal_tables it on p.object_id = it.object_id
Run Code Online (Sandbox Code Playgroud)

查询从一些 DMV获取 aDbSizeSpaceUsed列。

DbSize

一个简单的查询,获取文件类型所在的大小

  • = 0 = Rows
  • = 2 = FILESTREAM
  • = 4 = Full-text

此查询获取除日志大小之外的所有文件大小。

我假设这是稍后添加的,因为它会添加到属性窗格中的总大小中。

SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df WHERE df.type in ( 0, 2, 4 ) ) AS [DbSize]
Run Code Online (Sandbox Code Playgroud)

SpaceUsed

大一点,先从 sys.allocation_units DMV

...SUM(a.total_pages) + ... 
FROM
sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id
...
Run Code Online (Sandbox Code Playgroud)

然后将任何文件流数据添加到此数字(如果没有,则添加0):

...(SUM(a.total_pages) + (SELECT ISNULL(SUM(CAST(df.size as bigint)), 0) FROM sys.database_files AS df WHERE df.type = 2 )
FROM
sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id ...
Run Code Online (Sandbox Code Playgroud)

总查询

运行总查询给我:

DbSize  SpaceUsed
2557952 886791
Run Code Online (Sandbox Code Playgroud)

theDBSizeSpaceUsedcolumn 都是以8KB页为单位的大小。

我该怎么做才能获得与属性对话框显示的可用空间完全相同的数字?

如果我改变了查询被划分/128.0和减去SpaceUsedDBSize喜欢你的查询

SELECT
(SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df WHERE df.type in ( 0, 2, 4 ) )/ 128.0 -
(SUM(a.total_pages) + (SELECT ISNULL(SUM(CAST(df.size as bigint)), 0) FROM sys.database_files AS df WHERE df.type = 2 ))/ 128.0 AS [FreeSpace]
FROM
sys.partitions p join sys.allocation_units a on p.partition_id = a.container_id left join sys.internal_tables it on p.object_id = it.object_id
Run Code Online (Sandbox Code Playgroud)

我可以复制可用空间的属性视图:

FreeSpace
13055,945313
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

仍然需要在逗号后使用 2 位数字进行四舍五入

您的查询在我的数据库中给我的金额较低

FreeSpaceMB
13055.687500
Run Code Online (Sandbox Code Playgroud)

试图找出原因

假设

我们确定DBSize两个查询的列是相同的,区别应该是total_pages来自sys.allocation_unitsdmv的列和FILEPROPERTY函数

FILEPROPERTY(name, 'SpaceUsed') AS INT).
Run Code Online (Sandbox Code Playgroud)

FILEPROPERTY文档上:

文件中分配的页数

来源

其中total_pages=

此分配单元分配或保留的页面总数。

来源

猜测

我们得到所有这些分配单元的总和。我的猜测是,不同之处在于文件具有更多的开销页,而不是直接在分配单元 dmv 中,例如文件头、PFSGAMSGAMDCMBCM

更多关于这些在这里

使用sp_spaceused@updateusage更新空间使用信息 ( DBCC UPDATEUSAGE)

exec sp_spaceused
Run Code Online (Sandbox Code Playgroud)

sp_spaceused过程给出与“SSMS属性”窗口和sys.allocation_units查询相同的结果。

unallocated space
13055.95 MB
Run Code Online (Sandbox Code Playgroud)

但是当运行 sp_spaceused 时 @updateusage = 'true'

指示应运行 DBCC UPDATEUSAGE 以更新空间使用信息。当不指定objname时,语句在整个数据库上运行; 来源

EXEC sys.sp_spaceused  @updateusage = 'true'; 
Run Code Online (Sandbox Code Playgroud)

值更新:

unallocated space
13056.07 MB
Run Code Online (Sandbox Code Playgroud)

使用的已更改 SSMS 查询sys.allocation_units也显示了此更新值:

FreeSpace
13056,070313
Run Code Online (Sandbox Code Playgroud)

虽然FILEPROPERTY查询没有改变!

SELECT         size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS INT)/128.0 AS FreeSpaceMB 
    FROM sys.database_files; 

FreeSpaceMB
13055.687500
Run Code Online (Sandbox Code Playgroud)