Ich habe eine Tabelle in einer Produktionsdatenbank mit einer Größe von 525 GB, von denen 383 GB nicht verwendet werden:
Ich möchte einen Teil dieses Speicherplatzes zurückfordern, aber bevor ich mich mit der Produktionsdatenbank beschäftige, teste ich einige Strategien für eine identische Tabelle in einer Testdatenbank mit weniger Daten. Diese Tabelle hat ein ähnliches Problem:
Einige Informationen zur Tabelle:
- Der Füllfaktor wird auf 0 gesetzt
- Es gibt ungefähr 30 Spalten
- Eine der Spalten ist ein LOB vom Typ Image, in dem Dateien mit einer Größe von wenigen KB bis zu mehreren hundert MB gespeichert werden
- Der Tabelle sind keine hypothetischen Indizes zugeordnet
Auf dem Server wird SQL Server 2017 (RTM-GDR) (KB4505224) - 14.0.2027.2 (X64) ausgeführt. Die Datenbank verwendet das SIMPLE
Wiederherstellungsmodell.
Einige Dinge, die ich ausprobiert habe:
- Wiederaufbau der Indizes:
ALTER INDEX ALL ON dbo.MyTable REBUILD
. Dies hatte vernachlässigbare Auswirkungen. - Umordnung der Indizes:
ALTER INDEX ALL ON dbo.MyTable REORGANIZE WITH(LOB_COMPACTION = ON)
. Dies hatte vernachlässigbare Auswirkungen. Kopierte die LOB-Spalte in eine andere Tabelle, löschte die Spalte, erstellte die Spalte neu und kopierte die Daten zurück (wie in diesem Beitrag erläutert: Freigeben von nicht verwendetem Speicherplatz in der SQL Server-Tabelle ). Dadurch wurde der ungenutzte Speicherplatz verkleinert, aber scheinbar nur in belegten Speicherplatz umgewandelt:
Verwenden Sie das Dienstprogramm bcp, um die Tabelle zu exportieren, zu kürzen und neu zu laden (wie in diesem Beitrag erläutert: Freigeben des nicht verwendeten Speicherplatzes für eine Tabelle ). Dadurch wurde auch der nicht genutzte Speicherplatz reduziert und der genutzte Speicherplatz in einem ähnlichen Ausmaß wie im obigen Bild vergrößert.
- Obwohl dies nicht empfohlen wird, habe ich die Befehle DBCC SHRINKFILE und DBCC SHRINKDATABASE ausprobiert, aber sie hatten keine Auswirkungen auf den nicht verwendeten Speicherplatz.
- Laufen
DBCC CLEANTABLE('myDB', 'dbo.myTable')
machte keinen Unterschied - Ich habe all das versucht, während die Bild- und Textdatentypen beibehalten wurden und nachdem die Datentypen in varbinary (max) und varchar (max) geändert wurden.
- Ich habe versucht, die Daten in eine neue Tabelle in einer neuen Datenbank zu importieren. Dabei wurde auch nur der nicht verwendete Speicherplatz in den verwendeten Speicherplatz konvertiert. Ich habe die Details dieses Versuchs in diesem Beitrag beschrieben .
Ich möchte diese Versuche nicht in der Produktionsdatenbank durchführen, wenn dies die erwarteten Ergebnisse sind.
- Warum wird der ungenutzte Speicherplatz nach einigen dieser Versuche nur in benutzten Speicherplatz konvertiert? Ich habe das Gefühl, ich habe kein gutes Verständnis dafür, was unter der Haube passiert.
- Kann ich noch etwas tun, um den nicht genutzten Speicherplatz zu verringern, ohne den genutzten Speicherplatz zu vergrößern?
BEARBEITEN: Hier ist der Datenträgernutzungsbericht und das Skript für die Tabelle:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MyTable](
[Column1] [int] NOT NULL,
[Column2] [int] NOT NULL,
[Column3] [int] NOT NULL,
[Column4] [bit] NOT NULL,
[Column5] [tinyint] NOT NULL,
[Column6] [datetime] NULL,
[Column7] [int] NOT NULL,
[Column8] [varchar](100) NULL,
[Column9] [varchar](256) NULL,
[Column10] [int] NULL,
[Column11] [image] NULL,
[Column12] [text] NULL,
[Column13] [varchar](100) NULL,
[Column14] [varchar](6) NULL,
[Column15] [int] NOT NULL,
[Column16] [bit] NOT NULL,
[Column17] [datetime] NULL,
[Column18] [varchar](50) NULL,
[Column19] [varchar](50) NULL,
[Column20] [varchar](60) NULL,
[Column21] [varchar](20) NULL,
[Column22] [varchar](120) NULL,
[Column23] [varchar](4) NULL,
[Column24] [varchar](75) NULL,
[Column25] [char](1) NULL,
[Column26] [varchar](50) NULL,
[Column27] [varchar](128) NULL,
[Column28] [varchar](50) NULL,
[Column29] [int] NULL,
[Column30] [text] NULL,
CONSTRAINT [PK] PRIMARY KEY CLUSTERED
(
[Column1] ASC,
[Column2] ASC,
[Column3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column4] DEFAULT (0) FOR [Column4]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column5] DEFAULT (0) FOR [Column5]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column15] DEFAULT (0) FOR [Column15]
GO
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [DF_Column16] DEFAULT (0) FOR [Column16]
GO
Hier sind die Ergebnisse der Ausführung der Befehle in Max Vernons Antwort:
╔════════════╦═══════════╦════════════╦═════════════════╦══════════════════════╦════════════════════╗
║ TotalBytes ║ FreeBytes ║ TotalPages ║ TotalEmptyPages ║ PageBytesFreePercent ║ UnusedPagesPercent ║
╠════════════╬═══════════╬════════════╬═════════════════╬══════════════════════╬════════════════════╣
║ 9014280192║ 8653594624║ 1100376║ 997178 ║ 95.998700 ║ 90.621500 ║
╚════════════╩═══════════╩════════════╩═════════════════╩══════════════════════╩════════════════════╝
╔═════════════╦═══════════════════╦════════════════════╗
║ ObjectName ║ ReservedPageCount ║ UsedPageCount ║
╠═════════════╬═══════════════════╬════════════════════╣
║ dbo.MyTable ║ 5109090 ║ 2850245 ║
╚═════════════╩═══════════════════╩════════════════════╝
AKTUALISIEREN:
Ich habe folgendes ausgeführt, wie von Max Vernon vorgeschlagen:
DBCC UPDATEUSAGE (N'<database_name>', N'<table_name>');
Und hier war die Ausgabe:
DBCC UPDATEUSAGE: Usage counts updated for table 'MyTable' (index 'PK_MyTable', partition 1):
USED pages (LOB Data): changed from (568025) to (1019641) pages.
RSVD pages (LOB Data): changed from (1019761) to (1019763) pages.
Dadurch wurde die Datenträgerverwendung für die Tabelle aktualisiert:
Und die Gesamtbelegung der Festplatte:
Es sieht also so aus, als ob das Problem darin bestand, dass die Datenträgernutzung, die von SQL Server verfolgt wurde, nicht mehr mit der tatsächlichen Datenträgernutzung synchronisiert war. Ich werde dieses Problem als gelöst betrachten, aber ich würde gerne wissen, warum dies überhaupt passiert wäre!
DBCC CHECKDB
? Haben Sie darüber nachgedacht , von den sich bewegenden entfernt veraltete Datentypen , text
und image
? Sie könnten zu den falschen Statistiken beitragen.