Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Eingrenzen der Datentypen in einer sehr großen Tabelle

Zunächst einmal vielen Dank, dass Sie dies tun. Es ist ein so offensichtlicher Gewinn, dass viele keinen großen Wert darin sehen würden, aber es wird sich lohnen :). Die Welt ein bisschen gesünder machen.

Bezüglich IsActive ein boolescher Wert sein. Ich vermute, dass Sie darüber nachdenken, daraus ein BIT zu machen aufstellen. Das mag der richtige Weg sein, aber manchmal ist es besser, mit TINYINT zu gehen da die Möglichkeit besteht, die Bedeutung auf mehr als 2 Zustände auszudehnen. In diesem Fall wird es wirklich mehr zu StatusID . Normalerweise beginnt etwas vereinfacht als Aktiv / Inaktiv , aber später vielleicht gelöscht und/oder andere. Aus Sicht der Größe TINYINT ist immer 1 Byte. Andererseits BIT ist 1 Byte für bis zu 8 BIT Felder . Das heißt, ein BIT Feld ist 1 Byte, 2 BIT Felder ist ebenfalls ein Byte, und so weiter bis zu 8 BIT Felder werden in einem einzelnen Byte gespeichert. Es gibt also keine Platzersparnis, wenn Sie BIT wählen über TINYINT wenn die Tabelle nur 1 BIT hat aufstellen. Nur etwas zu beachten.

Wie Sie gesehen haben, ist ein ALTER TABLE für eine große Tabelle etwas viel. Eine Option, wenn auch nicht besonders gut, ist das Hinzufügen eines NOT NULL Feld--Number_1new --mit einem DEFAULT Wert (dies wird aufgrund der Vorgabe sofort erfolgen, zumindest beginnend mit SQL 2012), den keiner von ihnen natürlicherweise haben würde (z. B. 255), und dann langsam die Werte in einer Schleife migrieren, wie in:

UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;

Und wenn das erledigt ist, tue:

sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';

Natürlich ist es am besten, das in eine TRANSACTION zu verpacken, und das in ein TRY / CATCH. Wenn der zugehörige Code aktualisiert und alles getestet wurde und die Daten gut aussehen, können Sie Number_1old löschen Spalte.

Der beste Weg, den ich gefunden habe, besteht jedoch darin, eine neue Tabelle zu erstellen, die Daten langsam zu übertragen und dann die Tabellen und den Code gleichzeitig auszutauschen. Ich habe die Schritte in einem Artikel auf SQL Server Central detailliert beschrieben:Restructure 100 Million Row (or mehr) Tabellen in Sekunden. SRSLY! (kostenlose Registrierung erforderlich). Falls es Probleme beim Aufrufen dieses Artikels gibt, hier die grundlegenden Schritte:

  1. Erstellen Sie eine neue Tabelle mit der idealen Struktur--[tableNew]. Wenn Sie die Enterprise Edition verwenden, sollten Sie erwägen, entweder die ROW- oder die PAGE-Komprimierung zu aktivieren, da diese manchmal hilfreich sein können. Aber bitte recherchieren Sie zuerst, da es Situationen gibt, in denen sie negative Auswirkungen haben. Es gibt eine Dokumentation auf MSDN, die Ihnen hilft, dies herauszufinden, sowie einige Tools, mit denen Sie potenzielle Einsparungen abschätzen können. Aber selbst wenn Sie die Komprimierung aktivieren, würde ich diese Aktion nicht als Ersatz für das Projekt ansehen, das Sie hier durchführen.
  2. Fügen Sie einen Trigger hinzu AFTER UPDATE, DELETE auf [Tabelle], um Änderungen synchron zu halten (aber Sie müssen sich keine Gedanken über neue Zeilen machen)
  3. Erstellen Sie einen SQL Agent-Job, der fehlende Zeilen stapelweise überspringt. Tun Sie dies in einer Schleife, die ein INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. Die WHERE- und ORDER BY-Klauseln hängen von der Situation ab. Sie sollten darauf ausgerichtet sein, den gruppierten Index optimal zu nutzen. Wenn der gruppierte Index der neuen Tabelle strukturell mit der alten/aktuellen Tabelle identisch ist, können Sie zu Beginn jeder Schleife MAX([id]) aus [tableNew] abrufen und damit die WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Erstellen Sie die neue Tabelle, triggern Sie sie auf die aktuelle Tabelle und führen Sie den SQL-Agent-Job etwa eine Woche vor der vollständigen Umstellung durch. Dieser Zeitrahmen kann sich je nach Ihrer Situation ändern, aber stellen Sie sicher, dass Sie sich genügend Zeit nehmen. Es ist weitaus besser für den Job, Zeilen zu migrieren und nur wenige auf einmal zu haben, als 100.000 vor dem vollständigen Satz zu sein, wenn die Veröffentlichung beginnen soll.
  6. Wenn geplant ist, die anderen verwandten Tabellen zu migrieren (die PK-Referenzen für die beiden FKs, die Sie in INT umwandeln möchten s), dann machen Sie diese Felder hier zu INT jetzt und fügen Sie den FK einfach nicht hinzu, bis diese anderen Tabellen migriert sind, um INT-Felder als ihre PKs zu haben. Sie möchten diese Tabelle nicht erneut erstellen müssen, nur um diese Änderung für die FK-Felder vorzunehmen.
  7. Während des Cutovers (natürlich in einem TRY / CATCH):
    1. ÜBERTRAGUNG BEGINNEN
    2. Führen Sie eine abschließende Zeilenzählung für beide Tabellen durch, um sicherzustellen, dass alles verschoben wurde (vielleicht möchten Sie die Zeilen vor der Veröffentlichung auf Plausibilität überprüfen, um sicherzustellen, dass der Auslöser die Aktualisierungen und Löschungen wie erwartet durchgeführt hat)
    3. benenne die aktuelle Tabelle in "alt" um
    4. benennen Sie die "neue" Tabelle um, damit sie die "neue" nicht enthält
    5. Löschen Sie den SQL Agent-Job (oder deaktivieren Sie ihn zumindest)
    6. umbenennen und abhängige Objekte wie Einschränkungen usw.
    7. VERPFLICHTEN