Speicherplatz beanspruchen, nachdem das Tabellenfeld entfernt wurde

16

Ich verwende SQL 2008 R2 und die Datenbank hat in den letzten 3 Jahren bis vor ungefähr 3 Monaten gut und schnell funktioniert. Aufgrund der enormen Ausdehnung dieser Tabelle verlieren wir langsam den Serverraum.

Ich habe gelesen, dass das Schrumpfen, wir wollen die Indizierung von db nicht verlieren, weil es jahrelang schnell funktionierte und wir wollen keine Fragmentierung verursachen.

Wir haben beschlossen, dieses Feld und alle seine Werte zu löschen : Gibt es eine Möglichkeit, das ntext-Feld und alle seine Werte zu löschen und Speicherplatz freizugeben, ohne die Indizierung zu entfernen, ohne die Datenbankleistung zu verringern?

Ich füge die Ausgabe der Datenbankgrößenabfrage bei, um Ihnen die Größenerweiterung der letzten 5 Monate zu zeigen.

Bildbeschreibung hier eingeben

user1021182
quelle

Antworten:

12

Wir haben beschlossen, dieses Feld und alle seine Werte zu löschen: Gibt es eine Möglichkeit, das ntext-Feld und alle seine Werte zu löschen und Speicherplatz freizugeben, ohne die Indizierung zu entfernen, ohne die Datenbankleistung zu verringern?

Ich würde empfehlen (von BOL:)

DBCC CLEANTABLE
(
    { database_name | database_id | 0 }
    , { table_name | table_id | view_name | view_id }
    [ , batch_size ]
)
[ WITH NO_INFOMSGS ]

DBCC CLEANTABLE beansprucht Speicherplatz zurück, nachdem eine Spalte mit variabler Länge gelöscht wurde. Eine Spalte variabler Länge kann einen der folgenden Datentypen haben: varchar, nvarchar, varchar (max), nvarchar (max), varbinary, varbinary (max), text, ntext, image, sql_variant und xml. Der Befehl beansprucht keinen Speicherplatz mehr, nachdem eine Spalte mit fester Länge gelöscht wurde.

!! VORSICHT !! ( Verwenden Sie eine sorgfältige Stapelgröße - es ist ratsam, diesen Parameter zu verwenden, wenn Ihre Tabelle sehr umfangreich ist) :

DBCC CLEANTABLE wird als eine oder mehrere Transaktionen ausgeführt. Wenn eine Chargengröße wird nicht angegeben, verarbeitet der Befehl die gesamte Tabelle in einer Transaktion und der Tisch ausschließlich während des Betriebes gesperrt ist . Bei einigen großen Tabellen können die Länge der einzelnen Transaktion und der erforderliche Protokollspeicherplatz zu groß sein. Wenn eine Stapelgröße angegeben ist, wird der Befehl in einer Reihe von Transaktionen ausgeführt, die jeweils die angegebene Anzahl von Zeilen enthalten. DBCC CLEANTABLE kann nicht als Transaktion in einer anderen Transaktion ausgeführt werden.

Dieser Vorgang wird vollständig protokolliert.

Eine einfache Reproduktion wird beweisen, dass dies DBCC CLEANTABLEbesser ist als das Schrumpfen (und keine Sorge vor Fragmentierung :-)

-- clean up
drop table dbo.Test

-- create test table with ntext column that we will drop later
create table dbo.Test (
    col1 int
    ,col2 char(25)
    ,col3 ntext
    );

-- insert  1000 rows of test data
declare @cnt int;

set @cnt = 0;

while @cnt < 1000
begin
    select @cnt = @cnt + 1;

    insert dbo.Test (
        col1
        ,col2
        ,col3
        )
    values (
        @cnt
        ,'This is a test row # ' + CAST(@cnt as varchar(10)) + 'A'
        ,REPLICATE('KIN', ROUND(RAND() * @cnt, 0))
        );
end

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

--drop the ntext column
ALTER TABLE dbo.Test DROP COLUMN col3 ;

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

--reclaim the space from the table
-- Note that my table is only having 1000 records, so I have not used a batch size
-- YMMV .. so find a maintenance window and you an appropriate batch size 
-- TEST TEST and TEST before implementing in PROD.. so you know the outcome !!
DBCC CLEANTABLE('tempdb', 'dbo.Test') ;

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Kin Shah
quelle
Nachdem Sie den Befehl DBCC CLEANTABLE ausgeführt haben, müssen Sie Ihren Clustered-Index neu erstellen, falls die Tabelle über einen verfügt, um den Speicherplatz zurückzugewinnen. ALTER INDEX Indexname ON YourTable REBUILD;
Herr TA
6

Für die meisten Teile beziehe ich mich auf Paul Randalls Blogserie Inside the Storage Engine .

Die einzige Möglichkeit, nicht verwendeten Speicherplatz aus Datenbankdateien in SQLServer zurückzugewinnen, besteht in der Verwendung des Befehls DBCC SHRINK, mit dem Daten in den Datenbankdateien neu zugeordnet und nach dem Entfernen aus der Global Allcation-Zuordnung aus der Datenbankdatei entfernt werden. Dieser Vorgang ist langsam, führt zu einer Fragmentierung in der Datenbank und ist sogar langsamer, wenn LOB-Seiten verarbeitet werden, da diese als verknüpfte Listen in den Datenbankdateien gespeichert werden.

Da Sie die NTEXT-Spalte löschen, müssen Sie vor dem Verkleinern warten, bis der Bereinigungsprozess für Geisterbilder die Daten gelöscht hat.

Wenn Sie jetzt viel freien Speicherplatz in den Datenbankdateien haben, schadet dies nicht. Wenn Sie über den Festplattenspeicher verfügen, wird durch die Sicherungskomprimierung der freie Speicherplatz in den Dateien berücksichtigt.

Wenn Sie die Dateien unbedingt verkleinern möchten, können Sie eine neue Dateigruppe mit der Datenbank erstellen und als Standard festlegen. Verschieben Sie dann die Tabellen in die neue Dateigruppe. Dies kann jedoch Zeit in Anspruch nehmen und Ausfallzeiten verursachen. Ich habe die hier von Bob Pusateri erläuterte Technik mit guten Ergebnissen angewendet .

Spörri
quelle
Wird der Prozess der Geister-Bereinigung den Platz reduzieren oder wird auch ein Verkleinern erforderlich sein?
user1021182
Sie müssen immer verkleinern, Der Bereinigungsprozess leert nur die zugewiesenen Seiten, aber entfernt sie nicht aus den Datenbankdateien
Spörri
1
@Spörri Since you are dropping the NTEXT column you will have to wait for the ghost cleanup process to drop the data before shrinking.Bitte siehe meine Antwort . Sie können verwenden DBCC CLEANTABLE, um den Raum freizugeben.
Kin Shah
4

Möchten Sie die Datenbankdateien verkleinern, weil Sie diesen Speicherplatz für andere Datenbanken / Nicht-DB-Dateien benötigen oder weil Sie Probleme mit der Ausführung dieser Datenbank haben?

Wenn es das zweite ist, haben Sie möglicherweise kein so großes Problem, wie Sie denken. Wenn ich richtig liege, besteht Ihr Problem darin, dass die Datenbank erweitert werden muss, um zusätzlichen Speicherplatz für neue Daten zu gewinnen. Sobald Sie die Spalte entfernen, wird der gesamte von dieser Spalte belegte Speicherplatz für neue Zeilen freigegeben, die Tabellen in der Datenbank hinzugefügt werden. Dies bedeutet, dass es länger dauern wird, bis Ihre Datenbank wachsen muss. In der Zwischenzeit würde ich etwas zusätzlichen Platz für Ihr Datenlaufwerk bekommen. Die meisten Datenbanken wachsen mit der Zeit und es ist schön, über einen gesunden freien Speicherplatz auf dem Laufwerk zu verfügen.

Kenneth Fisher
quelle
Wir haben nur noch 10 GB Speicherplatz und es wird auch in wenigen Tagen ausgehen. Wir haben alles, was wir vom Server entfernen konnten, entfernt, Bereinigungen verwendet und Windows-Updates gestoppt, alle entfernt und die Winsxs bereinigt. Jetzt müssen wir die Größe der
DB-
Denken Sie auch hier daran, dass nach dem Löschen der zusätzlichen Spalte das Wachstum der Datenbank für einige Zeit unterbrochen wird, während Sie den neuen Speicherplatz ausfüllen, den Sie freigegeben haben. Wenn Ihre Datenbank nach diesem Zeitpunkt noch wächst, benötigen Sie unbedingt zusätzlichen Speicherplatz für Ihre Datenbank. Fügen Sie Ihrem Server möglicherweise ein neues Laufwerk hinzu.
Kenneth Fisher
0

Ich würde eine Spiegeltabelle ohne die anstößige Spalte erstellen, alle Daten in diese Tabelle kopieren, das Original löschen und dann die Spiegeltabelle umbenennen.

ardochhoch
quelle
In diesem Fall müssen auch alle Indizes vorbereitet werden
user1021182
ja , die alle Indizes der Tabelle auswirken müssen auch fallen gelassen und neu erstellt werden .... gilt auch für andere Objekte in der Tabelle zB Referenzierung: Trigger
ardochhigh