Ich habe eine SQL-Tabelle in einer Live-Datenbank mit mehr als 6 Millionen Zeilen und möchte die Genauigkeit einer bestimmten Spalte erhöhen:
%Vor%Nun ist meine Frage, ob ich SQL Server jede Zelle neu berechnen und neue Werte in dieselbe Zelle zurückschreiben werde, wenn ich obige Abfrage ausführe. (Wenn ja, bedeutet das, dass die Ausführung sehr lange dauern wird und unsere anderen Aktivitäten in der Datenbank davon betroffen sind.) Oder wird die Anweisung anders ausgeführt?
Eine Umwandlung von decimal(8, 2)
in decimal(8, 4)
erhöht die Genauigkeit nicht; es erhöht die Skalierung .
Von dezimal / numerisch - TSQL :
Also hat sich die Gesamtzahl der Ziffern (und damit die Speicheranforderungen) nicht geändert.
Wenn Sie einen Wert über 9999.9999 haben, haben Sie eine schlechte Zeit in Form eines arithmetischen Überlauffehlers. Um alle möglichen (8, 2) Werte zu berücksichtigen, müssten Sie stattdessen die Spalte auf decimal(10, 4)
erhöhen.
Dies erhöht jedoch die Speicheranforderungen für Ihre Spalte von 5 auf 9 Byte. Dies entspricht einer update
-Anweisung in Bezug auf die Verfügbarkeit und das Transaktionslog.
Was ich aufgrund von Tests herausgefunden habe, ist, dass für mindestens SQL Server 2008 R2 die erhöhte Genauigkeit nur dann eine Aktualisierung der Daten zur Folge hat, wenn sich die Speicheranforderungen ändern. Im Wesentlichen , wenn der neue Genauigkeitswert der Spalte im gleichen Speicherbereich (oder kleiner und ohne Kürzung) liegt wie im vorherigen Beispiel, dann sind die Tabellendaten unverändert.
Bei einer 6-Millionen-Ringtabelle beträgt die Auswirkung auf das Transaktionsprotokoll etwa 2,5 GB. Es wird nicht notwendigerweise um diesen Betrag wachsen, aber so viel Speicherplatz wird es verbrauchen. Meine Tests verwendeten ungefähr 2 Millionen Zeilen und die alter
-Anweisung verursachte, dass die Protokolle von 1MB auf ~ 850MB anwuchsen.
Was die Leistung betrifft (wie lange es dauern wird), ohne etwas über die Hardware und die Last Ihres Servers zu wissen, ist es unmöglich zu sagen. Wenn Sie ausreichend besorgt waren, die Tabelle nicht an Ort und Stelle ändern zu wollen, ist Ihre beste Vorgehensweise wahrscheinlich ein Table-Swap:
Erstellen Sie eine neue Tabelle ( sales_tmp
) mit dem gewünschten Schema und kopieren Sie die Daten:
Wenn Sie sicherstellen können, dass die Tabelle " sales
" während des Vorgangs nicht geändert wird, brauchen Sie sich nicht darum zu kümmern, sie bei Transaktionen und Sperren zu verhindern. Andernfalls sollte eine Transaktion repeatable read
ausreichen und die Lesevorgänge in der Tabelle sales
während der Operation zumindest nicht blockieren.
Dann:
sales_tmp
bis sales
) Dies kann zu Problemen führen, wenn Sie in der betroffenen Tabelle eine Replikation oder andere nützliche Dinge eingerichtet haben. Das ist nicht einfach zu deaktivieren und wieder zu aktivieren, leider.
Wenn Sie sich Sorgen über die Auswirkungen auf das Transaktionsprotokoll der Aktualisierung von 6 Millionen Datensätzen machen, müssen Sie die Datensätze in Batches aktualisieren. Die Größe variiert je nach Ihren Bedürfnissen. Ich würde 1.000-10.000 empfehlen.
IMO, ich glaube nicht, dass Sie sich darüber wirklich Sorgen machen müssen, es sei denn, Ihr Datenbankserver ist wirklich um freien Speicherplatz bemüht, aber diese Information könnte sich für die Zukunft als nützlich erweisen.
Wenn Ihr Wiederherstellungsmodell SIMPLE ist, gilt dies auch für die Protokolleindämmung. Wenn es voll ist, sind die Dinge schwieriger.
Trotz allem, was Blam in seiner Antwort behauptet, wird seine Schleifenimplementierung absolut nicht eine Eindämmung der Transaktionsprotokolldatei garantieren.
Geben Sie am Ende des Schleifenrumpfs eine checkpoint
-Anweisung aus, um sicherzustellen, dass die Protokolldaten gelöscht werden. SQL Server führt dies regelmäßig aus und in den meisten Fällen werden Sie dies nicht bemerken, aber in einigen Fällen werden Sie . Unten ist stark simplified psudeocode:
Dies ist schwieriger, da das Protokoll unbegrenzt wächst, bis Sie eine Protokollsicherung durchführen, die die Protokollseiten als inaktiv markiert und es SQL Server ermöglicht, den bereits für die Protokolldateien reservierten Speicherbereich erneut zu verwenden. Ich werde darauf nicht näher eingehen, als einige Ressourcen zu empfehlen:
Ich komme nicht zu den gleichen Schlussfolgerungen / Befunden wie Matt
dezimal und numerisch (Transact-SQL)
Für die Datentypen dezimal und numerisch berücksichtigt SQL Server alle spezifische Kombination von Präzision und Skalierung als anderer Datentyp. Zum Beispiel werden Dezimal (5,5) und Dezimal (5,0) als unterschiedlich angesehen Datentypen.
(8,4) ist ein anderer Typ als (8,2) und muss umgewandelt werden.
Und Sie erhöhen nicht die Präzision. Gleiche Präzision - andere Skalierung.
dezimal (8,2) 12356.78 wird NICHT in Dezimalzahlen umgewandelt (8,2).
Ich testete in einer Dezimal (8,2) -Spalte, die diesen Wert enthielt. SSMS ließ mich nicht in Dezimal (8,4)
Sie müssen auf dezimal (10,4) gehen und es wird umgewandelt / umgewandelt
Dies schlägt auf dem Set @ dec84 = @ dec82;
fehl %Vor% Fügen Sie der vorhandenen Tabelle eine Spalte mit der richtigen Genauigkeit hinzu.
Kein Index.
Und füge es als letzte Spalte hinzu!
Wenn nicht die letzte Spalte, kann es versuchen, Daten um
Um die Transaktionsprotokollaktualisierung in Stapeln zu schützen
100 ist nur ein Beispiel
Wenn es indiziert ist, fügen Sie das hier hinzu Dann schließe mit einem
ab %Vor%Benennen Sie dann newCol in oldCol
umSo mache ich Schleifen, um das Transaktionslog zu enthalten Normalerweise in Chunks von 10000
%Vor%Tags und Links sql sql-server sql-server-2008 alter-table