web-dev-qa-db-fra.com

Pourquoi une suppression ne peut-elle pas augmenter l'espace inutilisé dans une table?

Si je peuplie le tableau suivant:

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

Résultats:

name           rows  reserved  data    index_size  unused
-------------- ----  --------- ------- ----------- ------
CleanTableTest 13    456 KB    440 KB  8 KB        8 KB

Mais alors si je supprime toutes les lignes:

delete dbo.CleanTableTest
go

exec sp_spaceused CleanTableTest
go

Résultats:

name           rows reserved data   index_size unused
-------------- ---- -------- ------ ---------- -------
CleanTableTest 0    88 KB    80 KB  8 KB       0 KB

Pourquoi après le processus de suppression de toutes les lignes dans le tableau, l'espace inutilisé n'a pas changé? Il reste à 0 kb.

6
itzik Paz

Vous avez vraiment besoin de regarder la définition de sp_spaceused Pour trouver votre réponse pourquoi unused est zéro.

exec sp_helptext 'sp_spaceused';
go

Jetez un coup d'œil à un extrait ici de la procédure stockée:

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

C'est copié directement de la définition de sp_spaceused. Prenez note de la manière dont unused est en fait défini: pages réservées soustraite par pages utilisées (à condition que les pages réservées sont supérieures aux pages utilisées, rationnellement et par programme).

C'est pourquoi c'est pourquoi votre colonne unused est ce qu'elle est. L'ingénierie inverse expliquera tout.

7
Thomas Stringer

Vous avez un tas. Les tas ne nettoient pas l'espace avec DELETEs Dans la plupart des cas. Vous pouvez tronquer la table, ou vous pouvez mettre un index en cluster sur la table. Les tas sont parfaits pour les systèmes inserts-lourds, mais pas génial s'il y a beaucoup de suppressions.

7
Rob Farley