【问题标题】:Checking for unused space in SQL Server database file检查 SQL Server 数据库文件中的未使用空间
【发布时间】:2017-04-26 17:12:15
【问题描述】:

我正在尝试使用我在 SO 某处找到的稍微修改过的查询版本来确定 SQL Server 数据库文件中有多少可用空间。

SELECT
    GETDATE() AS [Timestamp],
    [TYPE] = A.TYPE_DESC,
    [FILE_Name] = A.name,
    [FILESIZE_MB] = CONVERT(DECIMAL(10, 2), A.SIZE / 128.0),
    [USEDSPACE_MB] = CONVERT(DECIMAL(10, 2), A.SIZE / 128.0 - ((SIZE / 128.0) - CAST(FILEPROPERTY(A.NAME, 'SPACEUSED') AS INT) / 128.0)),
    [FREESPACE_MB] = CONVERT(DECIMAL(10, 2), A.SIZE / 128.0 - CAST(FILEPROPERTY(A.NAME, 'SPACEUSED') AS INT) / 128.0),
    [FREESPACE_%] = CONVERT(DECIMAL(10, 2), ((A.SIZE / 128.0 - CAST(FILEPROPERTY(A.NAME, 'SPACEUSED') AS INT) / 128.0) / (A.SIZE / 128.0)) * 100),
    [FILEGROUP_NAME] = fg.name,
    [File_Location] = A.PHYSICAL_NAME
FROM
    sys.database_files A 
LEFT JOIN 
    sys.filegroups fg ON A.data_space_id = fg.data_space_id 
WHERE 
    A.TYPE_DESC NOT LIKE 'LOG'
ORDER BY 
    A.TYPE desc, A.NAME;

由于从数据库中删除数据时数据库文件不会缩小,因此查询并不能完全提供我正在寻找的所有信息。

有什么方法可以知道SpaceUsed 文件属性中包含多少实际数据(与删除记录等导致的可用空间相比)?或者是做DBCC SHRINKDATABASE 之类的事情并更改文件的物理大小的唯一选择?

我查看了sp_spaceusedsys.dm_db_index_physical_stats 以及其他很多东西,但到目前为止还没有找到解决方案。

更新:我发现了一些我认为更接近我需要的东西,尽管我不确定它是否完全正确。从页面计数/平均使用的页面空间计算使用的空间看起来更接近我的预期。

SELECT 
    page_count,
    avg_page_space_used_in_percent
FROM 
    sys.dm_db_index_physical_stats(db_id('TestDB'), NULL, NULL, NULL, 'Detailed')

【问题讨论】:

    标签: sql sql-server sql-server-2014


    【解决方案1】:

    在 SSMS 中,尝试右键单击数据库,转到报告,然后是标准报告,然后选择磁盘使用情况。如果这对您不起作用,也许其他标准报告之一可以。

    在标准磁盘使用报告的饼图下方,您可以看到数据文件使用的磁盘空间

    【讨论】:

    • 感谢您的信息。这基本上是我从查询中得到的相同类型的东西,所以它并不完全符合我的要求。我实际上不确定我想要的是否可能。
    【解决方案2】:

    有几种方法可以做到这一点,我个人最喜欢的是未记录的 DBCC 命令 ShowFileStats。它输出数据库的数据文件列表、磁盘上的盘区总数以及正在使用的盘区的实际数量。

    对于那些不记得的,一个extent是8页,一个页是8 KB大小。因此,对这两个输出进行一些数学运算应该可以为您提供所需的信息。这是一个快速示例脚本。

    请注意,DBCC 命令在当前数据库的上下文中运行。您可以修改它并将其变成一个小循环。

    IF OBJECT_ID('tempdb..#tempDataUsage') IS NOT NULL DROP TABLE #tempDataUsage
    CREATE TABLE #tempDataUsage
    (
        [Fileid] INT,
        [FileGroup] INT,
        [TotalExtents] BIGINT,
        [UsedExtents] BIGINT,
        [Name] sysname,
        [FileName] varchar(256)
    )
    DECLARE @SQLStatement NVARCHAR(400) = 'USE msdb
    DBCC ShowFileStats'
    INSERT INTO #tempDataUsage
    EXEC (@SQLStatement)
    
    SELECT 
        (TotalExtents * 8 * 8) AS totalSpaceOndiskKB,
        (UsedExtents * 8 * 8) AS SpaceActuallyUsedKB,
        Name AS DbName,
        FileName 
    FROM 
        #tempDataUsage
    

    【讨论】:

    • 这将返回与我使用的查询基本相同的信息。我用另一种看起来很有希望的方法更新了这个问题。
    • @thephez 是的,DMV 可以工作。抱歉,我没有看到那个“实际数据”评论。您可能需要对 Database_Id 进行分组才能获得真实的总数。看起来 dmv 返回每个对象的结果。但是,如果您只是查看每个数据文件,我仍然更喜欢 ShowFilestats。 :)
    猜你喜欢
    • 1970-01-01
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2011-07-07
    • 1970-01-01
    相关资源
    最近更新 更多