为什么删除不会增加表中未使用的空间?

itz*_*Paz 6 sql-server delete tablespaces

如果我填充下表:

IF OBJECT_ID ('dbo.CleanTableTest', 'U') IS NOT NULL
    DROP TABLE dbo.CleanTableTest;
GO
CREATE TABLE dbo.CleanTableTest
    (FileName nvarchar(4000), 
    DocumentSummary nvarchar(max),
    Document varbinary(max)
    );
GO
-- Populate the table with data from the Production.Document table.
INSERT INTO dbo.CleanTableTest
    SELECT REPLICATE(FileName, 1000), 
           DocumentSummary, 
           Document
    FROM Production.Document;
GO

exec sp_spaceused CleanTableTest
go
Run Code Online (Sandbox Code Playgroud)

结果:

name           rows  reserved  data    index_size  unused
-------------- ----  --------- ------- ----------- ------
CleanTableTest 13    456 KB    440 KB  8 KB        8 KB
Run Code Online (Sandbox Code Playgroud)

但是如果我删除所有行:

delete dbo.CleanTableTest
go

exec sp_spaceused CleanTableTest
go
Run Code Online (Sandbox Code Playgroud)

结果:

name           rows reserved data   index_size unused
-------------- ---- -------- ------ ---------- -------
CleanTableTest 0    88 KB    80 KB  8 KB       0 KB
Run Code Online (Sandbox Code Playgroud)

为什么删除表中所有行后未使用的空间没有改变?它保持在 0 KB。

Rob*_*ley 8

你有一堆。DELETEs在大多数情况下,堆不会清除空间。您可以截断表,也可以在表上放置聚集索引。堆非常适合大量插入的系统,但如果有大量删除就不是很好了。


Tho*_*ger 7

您确实需要查看 的定义sp_spaceused才能找到为什么unused为零的答案。

exec sp_helptext 'sp_spaceused';
go
Run Code Online (Sandbox Code Playgroud)

看看这里的存储过程的片段:

begin
    /*
    ** Now calculate the summary data. 
    *  Note that LOB Data and Row-overflow Data are counted as Data Pages.
    */
    SELECT 
        @reservedpages = SUM (reserved_page_count),
        @usedpages = SUM (used_page_count),
        @pages = SUM (
            CASE
                WHEN (index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count)
                ELSE lob_used_page_count + row_overflow_used_page_count
            END
            ),
        @rowCount = SUM (
            CASE
                WHEN (index_id < 2) THEN row_count
                ELSE 0
            END
            )
    FROM sys.dm_db_partition_stats
    WHERE object_id = @id;

    /*
    ** Check if table has XML Indexes or Fulltext Indexes which use internal tables tied to this table
    */
    IF (SELECT count(*) FROM sys.internal_tables WHERE parent_id = @id AND internal_type IN (202,204,211,212,213,214,215,216)) > 0 
    BEGIN
        /*
        **  Now calculate the summary data. Row counts in these internal tables don't 
        **  contribute towards row count of original table.
        */
        SELECT 
            @reservedpages = @reservedpages + sum(reserved_page_count),
            @usedpages = @usedpages + sum(used_page_count)
        FROM sys.dm_db_partition_stats p, sys.internal_tables it
        WHERE it.parent_id = @id AND it.internal_type IN (202,204,211,212,213,214,215,216) AND p.object_id = it.object_id;
    END

    SELECT 
        name = OBJECT_NAME (@id),
        rows = convert (char(11), @rowCount),
        reserved = LTRIM (STR (@reservedpages * 8, 15, 0) + ' KB'),
        data = LTRIM (STR (@pages * 8, 15, 0) + ' KB'),
        index_size = LTRIM (STR ((CASE WHEN @usedpages > @pages THEN (@usedpages - @pages) ELSE 0 END) * 8, 15, 0) + ' KB'),
        unused = LTRIM (STR ((CASE WHEN @reservedpages > @usedpages THEN (@reservedpages - @usedpages) ELSE 0 END) * 8, 15, 0) + ' KB')

end
Run Code Online (Sandbox Code Playgroud)

这是直接从sp_spaceused. 注意如何unused实际定义的:保留页减去已用页(假设保留页大于已用页,合理和编程)。

所以这就是为什么你的unused专栏是这样的。逆向工程将解释这一切。