UPDATE mit JOIN auf 100mm-Platten, wie geht das besser? (in T-SQL)

11

Ich muss 100 Millionen Datensätze in einer einzelnen Tabelle aktualisieren, um die Tabelle zu normalisieren, indem der varchar-Wert einer Spalte einfach durch eine ID ersetzt wird. (Ich sage "Ersetzen", aber ich schreibe die ID wirklich in eine andere Spalte.)

Ich versuche, den Datensatz zu normalisieren. Die noch nicht normalisierten Daten haben keine Indizierung. Mein Gedanke war, dass ich keine Indizes für die Rohwerte erstellen und warten würde, sondern stattdessen die Fremdschlüssel indizieren würde, die die varchar-Werte nach Abschluss der Aktualisierung durch tinyint-Werte ersetzen.

UPDATE A
SET A.AutoClassID = B.AutoClassID
FROM AutoDataImportStaging.dbo.Automobile as A
JOIN AutoData.dbo.AutoClass as B on (A.AutoClassName = B.AutoClassName)

Hintergrund

  • Verwenden von MSSQL 2008 R2 auf Server 2008 R2
  • Server hat 8 GB RAM
  • Server hat ein RAID10, 7200 U / min SATA (nicht großartig, ich weiß, in der Produktion werden nur Daten gelesen und keine Daten geschrieben; plus der jüngste HD-Mangel machte dies aus Kostengründen notwendig)
  • Der Server verfügt über eine Dual-Quad-Core-Xeon-CPU
  • Die Maschine macht nichts anderes (derzeit nur für Entwickler, nur für diesen Prozess).
  • einfache Protokollierung aktiviert (? - aber wird immer noch protokolliert, damit ein Rollback durchgeführt werden kann?)
  • Beachten Sie, dass die Abfrage auf zwei verschiedene DBs verweist, was das wert ist
  • "Breite" eines Datensatzes in der Tabelle, der aktualisiert wird, beträgt 455 Bytes

Ressourcen während der Ausführung

  • Der physische Arbeitsspeicher ist voll
  • Die Festplatten-E / A ist maximal
  • CPU macht kaum etwas (Choke-Punkt ist I / O)
  • Die Laufzeit betrug 14 Stunden und es wird gezählt!

Ich vermute ein paar Dinge, wie ich einen Index für die Rohdaten benötige, obwohl ich die Spalte (AutoClassName) nach den Normalisierungsaktualisierungen löschen werde. Ich frage mich auch, ob ich anstelle des JOIN nur einen Datensatz nach dem anderen durchgehen sollte, was zu dem Zeitpunkt, als ich damit anfing, lächerlich schien, aber jetzt scheint es, dass das schneller gewesen wäre.

Wie kann ich meine Methodik für meine verbleibenden Normalisierungsaktualisierungen (ähnlich wie diese) schneller ändern?

Chris Adragna
quelle

Antworten:

7

Sie versuchen dies als einzelne (sehr große) Transaktion durchzuführen. Führen Sie das Update stattdessen in kleineren Stapeln durch.

Sie würden auch profitieren von:

  • Ein temporärer Index für AutoData.dbo.AutoClass.AutoClassName
  • Mehr RAM. Viel mehr RAM.
Mark Storey-Smith
quelle
1
+1 Ich bin mit der Stapelaktualisierung unter Verwendung der TOPKlausel einverstanden . Das wäre mein Ansatz.
Thomas Stringer
Wenn ich UPDATE TOP mache, brauche ich eine WHERE-Klausel (WHERE AutoClassID ist NULL)? Würde die WHERE-Klausel nicht einen neuen Performance-Hit einführen (einen Tabellenscan mache ich jetzt nicht). Zweifellos würde dies das RAM-Problem verringern, das ich mit dem JOIN habe.
Chris Adragna
Meine Antwort ist längst überfällig, aber in meinem Fall hat sich SET ROWCOUNT als am effektivsten erwiesen.
Chris Adragna
10

Ich würde einen anderen Ansatz wählen.

Anstatt vorhandene Tabellen zu aktualisieren, erstellen Sie einfach eine neue Tabelle, die das enthält, was Sie benötigen.

Dies wird mit ziemlicher Sicherheit schneller sein:

SELECT DISTINCT
    AutoClassID,
    <Other fields>
INTO
    AutoDataImportStaging.dbo.Automobile
FROM
    AutoData.dbo.AutoClass

Wie derzeit geschrieben, passieren viele logische Operationen:

  • Lesen Sie alle Werte von A.AutoClassName
  • Lesen Sie alle Werte von B.AutoClassName
  • Vergleichen Sie die Werte A und B.
  • Lesen Sie von der übereinstimmenden Menge alle Werte von B.AutoClassID
  • Aktualisieren Sie vorhandene Werte von A.AutoClassId so, dass sie über alle vorhandenen Indizes der B.AutoClassId-Wert sind
JNK
quelle
Dies klingt nach einem netten, einfachen Ansatz, insbesondere angesichts des Festplatten-E / A-Problems, das ich habe. Danke, dass du so schnell geantwortet hast.
Chris Adragna
1
Ich schlage vor, dass Sie überprüfen, ob in Ihren Protokoll- und Datendateien genügend freier Speicherplatz vorhanden ist. Wenn die Dateien automatisch wachsen, sinkt die Leistung. Ich sehe oft Leute, die ein großes, einmaliges Update ausführen und ihre Protokolldatei automatisch vergrößern, ohne es zu merken.
Straße
5

Es wird nicht schneller sein, den Tisch eine Reihe nach der anderen zu durchlaufen!

Wie vermutet und von Ihnen bestätigt, ist dies E / A-gebunden - mit einer Festplatte konkurrieren Lese-, Schreib-, Transaktionsprotokolle und (beliebiger) temporärer Arbeitsbereich alle um dieselbe E / A.

Durch einfache Wiederherstellung werden die Transaktionen weiterhin protokolliert, das Protokoll wird jedoch von einem Prüfpunkt gelöscht. Es ist möglich, dass Ihre anfängliche Protokollgröße und die Einstellungen für das automatische Wachstum zu einer gewissen Verlangsamung der E / A führen. Das Transaktionsprotokoll muss vergrößert werden, um die Änderungen zu berücksichtigen.

Haben Sie versucht, das Feld AutoClassName zu indizieren? Wie viele verschiedene AutoClass-Werte gibt es?

Möglicherweise müssen Sie die Aktualisierungen stapelweise ausführen, basierend auf den Einschränkungen Ihrer E / A. Also 1 Million aktualisieren, Checkpoint, wiederholen ....

Kev Riley
quelle
Es gibt nur 15 verschiedene AutoClass-Werte. Ihre Kommentare bestätigen viele meiner Vermutungen (und Schmerzen!). Danke für die Antwort.
Chris Adragna
3

Erstellen Sie Indizes für die Verknüpfungsfelder.

Sie können die Indizes jederzeit löschen, wenn Sie fertig sind.

Ich wäre sehr überrascht, wenn die Indizes die Update-Leistung nicht wesentlich verbessern würden.

Jimbo
quelle
Ich bin sicher, dass sich die Indizes verbessern würden. Ich nehme an, die Frage ist, ob sie sich mehr verbessern als die Zeit, die zum Erstellen des Index benötigt wird (nur für eine Verwendung). Wahrscheinlich ja. :)
Chris Adragna
3

Exportieren Sie nach Ihren Wünschen, erstellen Sie eine neue Tabelle und importieren Sie sie zurück. Als Bonus hätten Sie eine Kopie der Daten als Backup, falls Wunder geschehen sollten.

srini.venigalla
quelle