Wird das Erhöhen der Genauigkeit einer Spalte mit ALTER die Datenbankleistung beeinträchtigen, während sie auf Massendaten ausgeführt wird?

8

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?

    
CIPHER 22.09.2014, 12:34
quelle

2 Antworten

6

Eine schnelle Korrektur

Eine Umwandlung von decimal(8, 2) in decimal(8, 4) erhöht die Genauigkeit nicht; es erhöht die Skalierung .

Von dezimal / numerisch - TSQL :

  • Genauigkeit Die maximale Gesamtanzahl der Dezimalstellen, die gespeichert werden können, sowohl links als auch rechts vom Dezimalpunkt .
  • scale Die maximale Anzahl der Dezimalstellen, die gespeichert werden können rechts vom Dezimalzeichen . Maßstab muss ein Wert von 0 bis p sein.

Also hat sich die Gesamtzahl der Ziffern (und damit die Speicheranforderungen) nicht geändert.

Die Antwort

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:

%Vor%

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:

  1. Replizieren Sie Berechtigungen für die neue Tabelle
  2. Erstellen Sie Indizes & amp; Fremdschlüsselreferenzen
  3. Alte Tabelle löschen
  4. Neue umbenennen ( 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.

Transaktionsprotokoll

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.

SIMIPLE Wiederherstellung

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:

%Vor%

Vollständige Wiederherstellung

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:

md4 23.09.2014, 11:09
quelle
2

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)

ändern

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

zu verschieben

Um die Transaktionsprotokollaktualisierung in Stapeln zu schützen
100 ist nur ein Beispiel

%Vor%

Wenn es indiziert ist, fügen Sie das hier hinzu Dann schließe mit einem

ab %Vor%

Benennen Sie dann newCol in oldCol

um

So mache ich Schleifen, um das Transaktionslog zu enthalten Normalerweise in Chunks von 10000

%Vor%     
paparazzo 23.09.2014 16:17
quelle