2016-04-05 4 views
3

Ich habe etwa 300 Tabellen mit je 5,5kk Zeilen. Eine der Zeilen verwendet nvarchar (128) als Datentyp (SQL Server 2012).
Wir haben uns entschieden, dies in int zu ändern und FK zur Dictionary-Tabelle mit allen nvarchars hinzuzufügen.DBCC CLEANTABLE befreit nicht genutzten Speicherplatz

Nachdem ich alles getan habe, habe ich die nvarchar Spalte entfernt, aber die Größe der Tabellen blieb gleich. Ich habe DBCC CLEANTABLE verwendet und die Indizes neu erstellt, um freien Speicherplatz zurückzugewinnen, aber die Größe der Tabelle ändert sich immer noch nicht.

Bis jetzt ist die einzige Möglichkeit, die ich gefunden habe, alle Daten in die neue Tabelle zu kopieren.

Frage: Was fehlt mir hier? Warum wird der Raum immer noch als gebraucht markiert und ich kann nicht durch Schrumpfen oder CREANTABLE-Befehl frei werden?

Vielen Dank!

Answ: Sieht aus wie die Antwort war ziemlich einfach und ich konnte es wegen meines Mangels an Wissen nicht finden. Das Hauptproblem hier war Haufen Fragmentierung. Diese Abfrage arbeitete für mich:

ALTER TABLE [TABLE_NAME] REBUILD 

Ich bin nicht sicher, dass es der beste Weg ist, aber zumindest ist es eine Arbeitsgruppe ein.

Edited1: Sorry, ich glaube, ich vergaß zu erwähnen - ich Index auf dem Textfeld gruppierten hatte, also musste ich den Index entfernen, um in der Lage zu entfernen, tatsächlich das Feld. Jetzt habe ich keine Indizes.

Edited2:

alte Tabelle:

CREATE TABLE [dbo].[Data_](
    [ID] [bigint] PRIMARY KEY IDENTITY(1,1) NOT NULL, 
    [Text] [nvarchar](128) NOT NULL, 
    [Category] [tinyint] NOT NULL, 
    [Country] [nvarchar](2) NOT NULL, 
    [ImportTimestamp] [date] NOT NULL 
) 

neue Tabelle:

CREATE TABLE [dbo].[Data_New](
    [ID] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL, 
    [Category] [tinyint] NOT NULL, 
    [Country] [nvarchar](2) NOT NULL, 
    [TextID] [int] NOT NULL) 

ALTER TABLE [dbo].[Data_New] WITH CHECK ADD FOREIGN KEY([TextID]) 
REFERENCES [dbo].[Dictionary] ([Id]) 

Copy-Skript:

INSERT INTO Data_New 
     ([Category] 
     ,[Country] 
     ,[TextID]) 
SELECT 
     [Category] 
     ,[Country] 
     ,[TextID] 
    FROM Data_ 

Antwort

1

Wenn Sie kümmern sich nicht um das Problem zu verstehen und wollen einfach nur von den Index dann loszuwerden Wiederaufbau ist ein sicherer Weg, alle Abfälle zu entfernen. Dies liegt daran, dass eine Indexrekonstruktion die physischen Datenstrukturen neu erstellt. Was auch immer der alte Index enthielt, spielt keine Rolle mehr.

Beim Vergleich mit CLEANTABLE sind Kompromisse erforderlich. Wenn eine Neuerstellung den Job für Sie erledigt, würde ich das immer tun, weil es eine so komplette Lösung ist.

Wenn ich "index" in dieser Antwort sage, meine ich alle physischen Strukturen, die eine der Spalten enthalten, die Ihnen wichtig sind. Das können B-Tree-Indizes oder der Heap sein, auf dem die Tabelle basiert.

+0

Dies deckt nicht die Daten der gesamten Tabelle? Oder meinen Sie, den Clustered Index neu aufzubauen, falls verfügbar? – Jeffrey

+0

Er kann alles wiederherstellen, was er will, zum Beispiel jeden Index einzeln. Die meisten Tabellen haben ein CI, so dass er alle Indizes neu aufbauen muss, die eine der Spalten enthalten, die ihm wichtig sind. Wenn es ein Heap ist, muss er den Heap neu erstellen, was dazu führt, dass auch alles andere neu erstellt wird. Mit dieser einfachen Antwort hoffe ich, dass es einfach in Ordnung ist, alles wieder aufzubauen. Wenn nicht, dann gilt die Antwort nicht für das OP, sondern vielleicht für zukünftige Besucher. – usr

+0

Nun, ich versuche, das Problem zu verstehen, aber ich habe Index nur auf einem Feld für die Suche verwendet und nein, ich lösche dieses Feld tatsächlich und ich entfernte den aktuellen Index, weil es einfach nicht mehr gültig ist. Und ich kann nicht glauben, dass ich einen Tisch von 900 mb habe und ein Index belegt 700 mb davon. –

2

Sind Sie su Soll die Tabelle wegen dieser Spaltenänderung kleiner werden? nvarchar (128) bedeutet nicht, dass SQL Server 128 Byte (+2) zum Speichern von Daten zuweist, z. B. die Zeichenfolge 'test'. Die Zeichenfolge 'test' benötigt nur 6 Bytes. Vielleicht müssen Sie zunächst freien Speicherplatz in der Tabelle überprüfen:

SELECT 
    t.NAME AS TableName, 
    s.Name AS SchemaName, 
    p.rows AS RowCounts, 
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB 
FROM 
    sys.tables t 
INNER JOIN  
    sys.indexes i ON t.OBJECT_ID = i.object_id 
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id 
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id 
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id 
WHERE 
    t.NAME = 'TABLE_NAME' 
    AND t.is_ms_shipped = 0' 
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows 
ORDER BY 
    t.Name 
+0

Wenn er die Daten in eine neue Tabelle kopiert, wird der Speicherplatz zurückgewonnen. Das kann also nicht das Problem sein. – usr

+0

Ich spreche nicht über ein Problem. Ich sage nur vielleicht gibt es überhaupt kein Problem .... – Jeffrey

+0

Das Problem ist der verschwendete Raum. Seine Existenz wird durch seine Aussage (hoffentlich wahr) bewiesen, dass das Kopieren der Daten in eine neue Tabelle es verkleinert. – usr

Verwandte Themen