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.
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.
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.