So beschleunigen Sie das Hinzufügen einer Spalte zu einer großen Tabelle in SQL Server

8

Ich möchte einer SQL Server-Tabelle eine Spalte mit etwa 10 Millionen Zeilen hinzufügen. Ich denke, diese Abfrage würde irgendwann das Hinzufügen der gewünschten Spalte beenden:

alter table T
add mycol bit not null default 0

aber es geht schon seit einigen Stunden. Gibt es eine Verknüpfung, um eine Spalte "nicht null Standard 0" in eine große Tabelle einzufügen? Oder ist das von Natur aus sehr langsam?

Dies ist SQL Server 2000. Später muss ich etwas Ähnliches auf SQL Server 2008 tun.

Chris
quelle

Antworten:

6

Abhängig von Ihrer Zeilengröße, Tabellengröße, Indizes usw. habe ich gesehen, wie SQL Server 2000 einige Stunden (4 bis 5 Stunden) abgeschwächt wurde, bevor es ENDLICH abgeschlossen wurde.

Das Schlimmste, was Sie jetzt tun können, ist "Panik" und das Ding hart zu töten. Lass es sich selbst auslaufen.

In Zukunft möchten Sie möglicherweise versuchen, das zu tun, was Farseeker erwähnt hat, eine zweite (leere) Struktur erstellen und Ihre Datensätze auf diese Weise kopieren.

  • Je länger die Tabellenzeile ist, desto länger dauert es.
  • Je mehr Indizes Sie für diese Tabelle haben, desto länger dauert es.
  • Wenn Sie einen Standardwert hinzufügen (was Sie getan haben), dauert es länger.
  • Wenn der Server stark ausgelastet ist, dauert es länger.
  • Wenn Sie diese Datenbank nicht sperren oder in den Einzelbenutzermodus versetzen, dauert es länger.

Wenn ich so hässliche Sachen machen muss, versuche ich es nachts zu machen ... wie 2 Uhr morgens, wenn niemand drauf ist (und die Wartung läuft NICHT auf dem Server).

Viel Glück! :-)

KPWINC
quelle
7

Hmm, 10 Millionen Zeilen sind einige, aber es liegt nicht außerhalb des Bereichs von MSSQL und das scheint sehr langsam zu sein.

Wir hatten einen Tisch mit einer riesigen Zeilengröße (schlecht gestaltet) und über 10 Millionen Zeilen. Als wir die Struktur ändern mussten, war es def. sehr langsam, also haben wir es getan (um den Tisch online zu halten, und das ist grob aus dem Gedächtnis, weil es schon lange her ist):

  • Neue Tabelle mit dem Suffix "C" (für die Konvertierung) und neuer Struktur (dh wie alte, jedoch mit neuer Spalte / Index / usw.) erstellt
  • SELECT * INTO tableC FROM Tabelle
  • sp_rename 'table' 'tableOld'
  • sp_rename 'tableC' 'table'

Auf diese Weise spielt es keine Rolle, wie lange die Konvertierung dauert, da die alten Daten online sind. Es kann jedoch zu Problemen mit Zeilen kommen, die während der Konvertierung in die Tabelle geschrieben werden (dies war für uns kein Problem, da die Daten nur einmal täglich geschrieben, aber tausende Male pro Stunde abgefragt wurden). Vielleicht möchten Sie dies untersuchen .

Mark Henderson
quelle
5

Sie können versuchen, jeden Schritt des Vorgangs in einem separaten Stapel auszuführen, z

alter table T add mycol bit null
go
update T set mycol = 0
go
alter table T alter column mycol bit not null
go
alter table T add default 0 for mycol
go

Vorteile sind:

  • Sie erhalten ein besseres Feedback über den Fortschritt des Vorgangs, da es sich nun um 4 separate Chargen handelt, die jeweils ungefähr 1/4 der Zeit in Anspruch nehmen.
  • Es verringert die Wahrscheinlichkeit von Timeout-Fehlern, wenn es mit clientseitigem Code ausgeführt wird.
  • Ich finde, dass es manchmal die Leistung verbessert.

Sie können auch versuchen, alle nicht gruppierten Indizes in der Tabelle abzulegen, bevor Sie die Änderung vornehmen, und sie anschließend wiederherzustellen. Das Hinzufügen einer Spalte kann durchaus umfangreiche Seitenaufteilungen oder andere Neuanordnungen auf niedriger Ebene beinhalten, und Sie können auf den Aufwand verzichten, nicht gruppierte Indizes zu aktualisieren, während dies geschieht.

Christian Hayter
quelle
Dieser Ansatz wird dringend empfohlen. Bei Bedarf können Sie diesen zweiten Schritt sogar in Blöcke aufteilen, sodass Sie jeweils nur eine Teilmenge von Zeilen aktualisieren, entweder basierend auf Primärschlüsselbereichen oder mithilfe von SET ROWCOUNT (für SQL 2000) oder UPDATE TOP 1000 (für SQL 2005) / 2008).
BradC
3

Dies wird eine ganze Weile dauern. Dies liegt daran, dass Sie den Standardwert hinzufügen. Dies führt dazu, dass der SQL Server alle Zeilen in einer einzigen Transaktion aktualisiert. Stellen Sie sicher, dass niemand anderes die Tabelle verwendet, da dies zu einer Blockierung Ihres Prozesses führt.

mrdenny
quelle
1

Ich habe ähnliche Dinge in einer Tabelle mit mindestens 65 Millionen Zeilen gemacht und es hat nicht so lange gedauert. Haben Sie genug Speicher und eine ausreichende Leistung im Festplattensystem?

Wenn Sie den Prozess beschleunigen möchten, können Sie alle Indizes entfernen, die Clustered-Index- und Fremdschlüsseleinschränkungen ausführen, bevor Sie die Tabelle ändern. Dies muss jedoch erfolgen, wenn das System nicht verwendet wird. Andernfalls können inkonsistente Daten auftreten. Am Ende müssen Sie jedoch die Fremdschlüssel und die Indizes anwenden, bevor Sie fertig sind. Sie werden jedoch die Schmerzen für das Transaktionsprotokoll lindern, zumindest wenn Sie ein einfaches Wiederherstellungsmodell verwenden. In SQL Server 2008 können Sie die Indizes mit ONLINE = on und SORT_IN_TEMPDB = on erstellen

Håkan Winther

Hakan Winther
quelle
0

Sie werden so etwas nicht wirklich verknüpfen - egal was Sie tun SQL Server muss einige Zeilen in allen Zeilen in der Tabelle verarbeiten.

Sie können sicherstellen, dass es so schnell wie möglich ausgeführt wird, indem Sie sicherstellen, dass sich Ihre Datendateien und Protokolle auf separaten Laufwerken befinden und die anderen üblichen Empfehlungen.

David Spillett
quelle
0

Stunden für 10m Reihen sind viel zu lang. Stellen Sie sicher, dass nichts die Schlösser auf dem Tisch offen hält.

ConcernedOfTunbridgeWells
quelle
0

Bei einem Schulungskurs hatte ich ein Gespräch mit einigen DBAs vom DoD. Sie verwalten MySQL-Datenbanken mit 100 TB und mehr. Tabellenänderungen werden mit Dump und Load durchgeführt, dies erfordert jedoch offensichtlich einige Ausfallzeiten. Sie erwähnten auch, dass sie dies aufgrund der Zeit nicht gerne mit Datenbanken über 10 TB tun.

Die Daten werden ausgegeben, sie haben nicht angegeben, was zu tun ist, aber ich würde SQL-Dateien annehmen. Die Tabellen werden dann abgeschnitten und das Schema nach Bedarf geändert. Die Daten werden dann neu geladen.

John Gardeniers
quelle
0

Hatten Sie zufällig eine Reihe von Indizes für Ihre Tabelle und möglicherweise sogar einen Clustered-Index für Ihre Tabelle T?

Ich hatte auch Probleme beim Hinzufügen einer neuen Spalte (es ist eine Identitätsspalte). Die Tabelle hatte 9,3 Millionen Zeilen und einen nicht gruppierten Index für den Primärschlüssel.

Wenn wir aus irgendeinem Grund den Index für Tabelle T löschen, fügen Sie anschließend die Spalte hinzu und fügen Sie dann den Index für Tabelle T wieder hinzu. Auf dem Standard SQLServer 2008 war er im Grunde 60-mal schneller.

Ich habe nicht herausgefunden, warum es so schnell ging, hoffentlich kann mir jemand eine Antwort darauf geben.

dsum
quelle
Der Grund, warum der Prozess 60x schneller wird, wenn der Index gelöscht wird, ist folgender: Wenn Sie einen Index haben, muss SQL Server die Datensätze in der Tabelle in einer bestimmten Reihenfolge anordnen. Wenn Sie einen Index für eine Spalte mit ABCF haben und "D" hinzufügen möchten, muss dieser Datensatz zwischen "C" und "F" eingefügt werden. Der Server muss zuerst die Position finden und dann den Datensatz einfügen. Daher der zeitaufwändige Vorgang beim Einfügen von Daten in indizierte Tabellen.
@Terminator Dies ist nur korrekt, wenn es sich um einen CLUSTERED- Index handelt. Ein regulärer Index hat keinen Einfluss auf die Tabellenreihenfolge. Er speichert lediglich einen Schlüsselwert und einen Index in der Datenbanktabelle (normalerweise in einem btree oder einer ähnlichen Struktur). Der Grund, warum der Index den ALTER TABLEBefehl verlangsamt, liegt darin, dass jeder Index aktualisiert werden muss (für 10 Millionen Zeilen pro Index) - eine erhebliche Menge zusätzlicher Festplatten-E / A und Zahlenkalkulation.
voretaq7