Gibt es eine zuverlässige Methode, um festzustellen, wann Sie DBCC CLEANTABLE ausführen sollten, um Speicherplatz zurückzugewinnen?

11

In letzter Zeit habe ich nicht nur Dateien vergrößert, wenn sie fast 80% der Dateien ausgelastet sind, sondern auch proaktiver Speicherplatz mithilfe der üblichen Tricks wie Defragmentieren von Heaps, Hinzufügen und Löschen von Clustered-Indizes, Implementieren der Zeilen- oder Seitenkomprimierung usw. zurückgewonnen.

Es gibt jedoch einige Fälle, in denen ich durch Ausführen von DBCC CLEANTABLE noch mehr Speicherplatz zurückgewinnen konnte . Bei Hunderten von Datenbanken in meiner Umgebung ist es nicht möglich zu wissen, was Benutzer in den einzelnen Datenbanken tun, und es ist völlig akzeptabel, dass Änderungen vorgenommen werden, bei denen Spalten mit fester Länge gelöscht werden. Ich habe diese Möglichkeiten normalerweise gefunden, indem ich mir die Anzahl der Zeilen und Seiten in einigen von mir geschriebenen Skripten zur Nutzung des Objektbereichs angesehen habe. Ich möchte noch einen Schritt weiter gehen und versuchen, die Erkennung solcher Szenarien zu automatisieren.

Was ich gerne wissen würde, ist, ob jemand da draußen aktiv nach solchen Möglichkeiten sucht und wenn ja, wonach suchen Sie konkret?

Meine Gedanken waren, etwas in die Richtung zu schreiben, wie die maximale und minimale Größe einer Zeile, die Anzahl der Zeilen in der Tabelle, die Anzahl der zugewiesenen Seiten und die Anzahl der verwendeten Seiten erfasst werden, und dann einige grundlegende Berechnungen durchzuführen, um die Ergebnisse zu protokollieren sind weit außerhalb dessen, was "erwartet" werden würde.

AndrewSQL
quelle
Ich empfehle dringend, den Parameter batch_size für große Tabellen zu verwenden. Dies führt dazu, dass der Befehl in einer Reihe von Transaktionen ausgeführt wird, im Gegensatz zu einer riesigen Transaktion.
Datum

Antworten:

11

Die Lösung für dieses Problem besteht darin, wöchentlich einen Job auszuführen, der sp_spaceused für alle Tabellen in einer Datenbank ausführt und diese Daten in einer Tabelle speichert. Wenn es Größenunterschiede für jede Tabelle gibt, die größer als 10% sind, würde ich den dbcc cleantable ausführen.

Mein Code zum Durchlaufen von Tabellengrößen sieht folgendermaßen aus:

if OBJECT_ID ('tempdb.dbo.#temp') is not null
    drop table #temp;

if OBJECT_ID ('dbo.BigTables') is not null
    drop table dbo.BigTables;
go

CREATE TABLE [dbo].[BigTables] (
    [table_name] [sysname] NOT NULL,
    [row_count] [int] NULL,
    [col_count] [int] NULL,
    [data_size] [varchar](50) NULL,
    [Date] [datetime] NOT NULL,
    [DBName] [nvarchar](128) NULL
);
GO

CREATE TABLE #temp (
    table_name sysname ,
    row_count int,
    reserved_size varchar(50),
    data_size varchar(50),
    index_size varchar(50),
    unused_size varchar(50)
);
go

INSERT     #temp
EXEC       sp_msforeachtable 'sp_spaceused ''?'''

insert into dbo.BigTables
SELECT     a.table_name,
           a.row_count,
           count(*) as col_count,
           a.data_size,
           getdate() as [Date],
    'MY DB' as DBName
FROM       #temp a
INNER JOIN information_schema.columns b
           ON a.table_name collate database_default
                = b.table_name collate database_default
GROUP BY   a.table_name, a.row_count, a.data_size
ORDER BY   CAST(Replace(a.data_size, ' KB', '') as integer) desc

DROP TABLE #temp;

Select * from dbo.BigTables;

Jetzt müssen Sie nur noch die Logik erstellen, die überprüft, wie sich die Größe im Laufe der Woche ändert, und sie planen.

Marian
quelle
Wenn es nun Gründe gibt, Ungenauigkeiten in den Tabellengrößenberichten zu vermuten, sollten Sie sich für DBCC UPDATEUSAGE entscheiden (dadurch werden die Zeilen- und Seitenzahlen korrigiert). Freut mich zu helfen!
Marian