Wie viel Speicherplatz benötige ich, um einer sehr großen Tabelle einen Primärschlüssel hinzuzufügen?

7

Ich verwende Microsoft SQL Server 2014 - 12.0.4100.1 Enterprise Edition (64-Bit) unter Windows NT 6.3 (Build 9600 :)

Ich habe eine 491-GB-Tabelle mit 3,6 Milliarden Zeilen ohne Primärschlüssel. Der Primärschlüssel, den ich hinzufügen möchte, deckt nur eine einzelne bigintSpalte ab, die eindeutige Werte enthält. Die Datenbank verfügt über 477 GB freien Speicherplatz, aber das scheint nicht genug zu sein.

Der Versuch, es hinzuzufügen, schlägt mit folgendem Fehler fehl:

Speicherplatz für Objekt 'dbo.SORT temporärer Ausführungsspeicher: 424251614560256' in Datenbank '[redigiert]' konnte nicht zugewiesen werden, da die Dateigruppe 'PRIMARY' voll ist. Erstellen Sie Speicherplatz, indem Sie nicht benötigte Dateien löschen, Objekte in der Dateigruppe löschen, der Dateigruppe zusätzliche Dateien hinzufügen oder das automatische Wachstum für vorhandene Dateien in der Dateigruppe aktivieren.

Der Datenbankname im Fehler ist die Datenbank, zu der ich die PK hinzufügen möchte, nicht 'tempdb', was ich häufig bei dieser Art von Fehler sehe.

Der Befehl, den ich benutze:

ALTER TABLE REDACTED ADD CONSTRAINT [PK_REDACTED] PRIMARY KEY CLUSTERED 
(
    [RedactedId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Zuerst schlug der Befehl nach 8 bis 9 Minuten fehl, dann fügte mein DBA der Datenbank auf einem Laufwerk mit etwa 150 GB freiem Speicherplatz eine weitere Datendatei hinzu. Das zweite Ausführen schlug nach 24 Minuten fehl. Das ist ein Fortschritt, aber ich habe keine Ahnung, wie viel freier Speicherplatz benötigt wird oder wie lange es tatsächlich dauern wird, diesen Index hinzuzufügen. Derzeit sind 477 GB in dieser Datenbank frei, aber das reicht anscheinend immer noch nicht aus, um diese Art auszuführen.

Gibt es eine Möglichkeit zu berechnen, wie viel Speicherplatz benötigt wird, um diesen Befehl mit 3,6 Milliarden bigintWerten auszuführen ? Oder gibt es einen anderen Trick, der zum Erfolg dieses Befehls beiträgt? Was bedeutet diese große Zahl im Fehler?

Glasiert
quelle
5
Die allgemeine Anleitung ist 2,5x, aber es gibt wahrscheinlich 50 Variablen, die in eine einigermaßen genaue Vorhersage einfließen. Wenn Sie ein Wartungsfenster öffnen können, können Sie stattdessen eine leere Tabelle mit dem gewünschten Schlüssel und Cluster-Index erstellen und diese dann delete...output intoin Stapeln mit gelegentlichen Checkpoint- / Sicherungsprotokollvorgängen verwenden, um zu verhindern, dass das Protokoll zu Ihrem Speicherplatzproblem wird . Die Nummer ist nur eine vom System generierte ID.
Aaron Bertrand
1
Da Sie einen Clustered-Index erstellen, werden alle Daten und nicht nur die Bigint-Werte verschoben.
Michael Green
Eine Reichweite, aber die Größe von TempDB erhöhen?
Paparazzo
Das Erstellen eines Clustered-Index wird in TempDB nicht durchgeführt.
Glasiert

Antworten:

4

Ich möchte auch hinzufügen, dass beim Erstellen eines Clustered-Index nicht nur Datenseiten verschoben werden, sondern auch alle Nicht-Clustered-Indizes neu erstellt werden müssen, da jede Zeile im Nicht-Clustered-Index einen Clustered-Schlüsselwert enthält. Alle diese Datenbewegungen müssen protokolliert werden, und beim Sortieren wird tempDb stark beansprucht, da Ihnen wahrscheinlich keine 500 GB Speicher zur Verfügung stehen, oder? ;)

Sie werden viele Debatten und unterschiedliche Meinungen über die Verwendung von Haufen finden, und ich spekuliere hier natürlich, aber höchstwahrscheinlich gibt es einen Grund, warum für eine so große Tabelle noch kein Clustered-Index definiert ist. Es ist nicht gerade die beste Vorgehensweise, aber manchmal ist es sinnvoll, eine Tabelle ohne Clustered-Index (schnelle, minimal protokollierte Einfügungen) mit einigen engen, nicht gruppierten Indizes zu definieren, die häufige Abfragen abdecken.

Die Entscheidung über das Hinzufügen eines Index (primär, gruppiert, nicht geclustert, XML, räumlich, ...) hängt natürlich von dem Problem ab, das Sie lösen möchten. Im OLTP-System optimieren Sie normalerweise Ihre Indizes, um die Schreibleistung zu verbessern, während Sie in Berichtssystemen wie OLAP normalerweise an Lesetypen von Workloads arbeiten müssen.

Und einige Vorschläge, um dies zusammenzufassen: - Der Primärschlüssel muss nicht geclustert werden. - Wenn die Tabelle nicht partitioniert ist, sollten Sie sie auf jeden Fall partitionieren. - Wenn Ihr Ziel darin besteht, bestimmte Arten von Abfragen schneller zu machen (und nicht zu versuchen, die Eindeutigkeit zu erzwingen Sie sollten in Betracht ziehen, einen zusätzlichen (oder geänderten) nicht gruppierten (möglicherweise gefilterten) Index oder eine indizierte Ansicht zu erstellen (ideal für aggregierte Abfragen).

Hoffe es hilft, viel Glück!

Jure Pirs
quelle