Ich bin derzeit mit der folgenden Situation gesegnet:
- Wir haben eine Produktionsdatenbank, die partitioniert ist und Primärschlüssel vom Typ verwendet
int
- Mehrere (~ 20) Tabellen mit jeweils> 100.000.000 Zeilen, von denen 2 in der Nähe von 2.000.000.000 Zeilen liegen
- Diese Tabellen haben alle eine Spalte vom Typ
int
als Primärschlüssel, die in jeder Zeile um eins erhöht wird - Diese Tabellen sind aufgeteilt, eine Partitionsfunktion des Typs verwendet
int
, unter VerwendungRIGHT(0)
, so effektiv alle Daten in dem einen und einzigen Partition
Da sich einige Tabellen dem int32
Maximalwert nähern, müssen wir diese Spaltentypen in ändern bigint
. Hier beginnen die Probleme:
Der Typ einer Primärschlüsselspalte kann nicht geändert werden (dies kann ich vermeiden, indem ich den Primärschlüssel lösche, den Typ ändere und den Primärschlüssel erneut erstelle). Ich kann den Spaltentyp jedoch nach dem Löschen der Primärschlüsseleinschränkung nicht ändern, indem ich die folgende Ausnahme:
{"Das Objekt 'XXX_XXX' ist abhängig von der Spalte 'ABCD'. ALTER TABLE ALTER COLUMN ABCD ist fehlgeschlagen, weil ein oder mehrere Objekte auf diese Spalte zugreifen."}
Soweit ich sehen kann, besteht eine schemagebundene Abhängigkeit des Partitionsschemas (und der Funktion) von der Tabelle, die die Änderung des Datentyps verhindert. Es gibt keine Fremdschlüssel, die auf diese Primärschlüssel verweisen.
Ich sehe keine Lösung für die Aktualisierung des Spaltentyps in dieser Datenbank, geschweige denn für eine Produktionsdatenbank. Wir können uns einige Wartungsausfälle leisten, z. B. + - 60 Minuten, aber nicht mehr. Was sind meine Optionen?
Zusätzliche Information
Ich fange an zu glauben, dass meine einzige Möglichkeit darin besteht, neue Tabellen mit der richtigen Struktur zu erstellen und die vorhandenen Tabellendaten in die neuen zu pumpen ...
Tabellen sind bereits anhand ihres Primärschlüsselwerts partitioniert (derzeit nur 1 Partition (
RIGHT(0)
zukünftige Partitionen sollten für neue Werte möglich sein (RIGHT(x)
), die Grenze mussx
noch festgelegt werden).Dies sind Datenprotokollierungstabellen, nur Einfügungen, keine Aktualisierungen oder Löschungen
Auf diesen Tabellen wird immer DML ausgeführt, mit Ausnahme von Wartungsfenstern, die alle 6-8 Wochen etwa 90 Minuten lang ausgeführt werden.
Die auf dem Primärschlüssel basierenden Indizes sind alle gruppiert
Diese Tabellen enthalten keine nicht gruppierten Indizes
quelle
Antworten:
Bevor ich eine Lösung vorstelle, möchte ich zunächst Ihre Annahme bestätigen:
Du hast Recht; Die Tatsache, dass Sie eine Partitionsfunktion für einen Datentyp von definiert haben,
INT
hindert Sie daran, den Datentyp Ihrer Spalte zu ändern ... Leider bleiben Sie bei der aktuellen Tabelle hängen, da es meines Wissens keine Möglichkeit gibt, Anpassungen vorzunehmen Der Datentyp einer Partitionsfunktion, ohne sie zu löschen oder neu zu erstellen. Dies ist nicht möglich, da Tabellen davon abhängig sind. Im Grunde ist dies das Henne-Ei- Szenario.Eine mögliche Lösung für Ihr Problem besteht darin, die Vorteile partitionierter Ansichten zu nutzen . Diese Funktionalität gibt es schon immer und wird oft übersehen. Eine partitionierte Ansicht bietet Ihnen jedoch die Möglichkeit, Ihr Datenlimit zu umgehen,
INT
indem Sie neue Daten zu einer anderen Tabelle hinzufügen, in der dieID
Spalte einBIGINT
Datentyp ist. Dieser neuen Tabelle sollte auch eine bessere Partitionsfunktion / ein besseres Partitionsschema zugrunde liegen, und sie wird hoffentlich in Zukunft etwas besser beibehalten. Alle Abfragen, die auf die alte Tabelle verweisen, werden dann auf die partitionierte Ansicht verwiesen, und es tritt kein Datenlimitproblem auf.Lassen Sie mich anhand eines Beispiels erklären. Das Folgende ist eine einfache Neuerstellung Ihrer aktuellen partitionierten Tabelle, die aus einer Partition besteht, wie folgt:
Nehmen wir als Argument an, dass ich mich dem
INT
Limit nähere (obwohl ich es offensichtlich nicht bin). Da mir nicht die gültigenINT
Werte in derID
Spalte ausgehen sollen, werde ich eine ähnliche Tabelle erstellen, sondern stattdessenBIGINT
für dieID
Spalte verwenden. Diese Tabelle wird wie folgt definiert:Ein paar Anmerkungen hier:
Tabellenpartitionierung in der neuen Tabelle
Diese neue Tabelle wird auch entsprechend Ihren Anforderungen partitioniert. Es ist eine gute Idee, über zukünftige Wartungsanforderungen nachzudenken. Erstellen Sie daher einige neue Dateigruppen, definieren Sie eine bessere Strategie für die Partitionsausrichtung usw. Mein Beispiel ist, es einfach zu halten, sodass ich alle meine Partitionen in eine Dateigruppe zusammenfasse. Tun Sie dies nicht in der Produktion, sondern befolgen Sie stattdessen die Best Practices für die Tabellenpartitionierung mit freundlicher Genehmigung von Brent Ozar et. al.
Überprüfen Sie die Einschränkung
Da ich partitionierte Ansichten nutzen möchte, muss ich
CHECK CONSTRAINT
dieser neuen Tabelle eine hinzufügen . Ich weiß, dass meine Einfügeanweisung ~ 440.000 Datensätze generiert hat. Um sicher zu gehen, werde ich meinenIDENTITY
Startwert bei 500.000 beginnen und auch eineCONSTRAINT
Definition erstellen . Die Einschränkung wird vom Optimierer verwendet, wenn bewertet wird, welche Tabellen beim Aufrufen der eventuellen partitionierten Ansicht entfernt werden können.Nun die beiden Tische zusammen pürieren
Partitionierte Ansichten eignen sich nicht besonders gut, wenn Sie gemischte Datentypen auf sie werfen, wenn es um die Partitionsspalte in den zugrunde liegenden Tabellen geht. Um dies zu umgehen, müssen wir die aktuelle
ID
Spalte in Ihrer aktuellen Tabelle alsBIGINT
Wert beibehalten. Dazu fügen wir eine persistierte berechnete Spalte wie folgt hinzu:Ich habe auch eine andere hinzugefügt
CHECK CONSTRAINT
auf dem alten Tisch (um Hilfe mit Partition Elimination von unserem eventuellen partitionierten View) und einem neuen Non-Clustered Index, der wird wirken wie ein Primärschlüsselindex (weil Look - Ups mit Ursprung aus der partitionierte Sicht gehen auftretenID_BIG
stattID
).Mit der neuen berechneten Spalten- und Prüfbeschränkung kann ich die partitionierte Ansicht schließlich wie folgt definieren:
Wenn Sie eine schnelle Abfrage für diese Ansicht ausführen, wird bestätigt, dass die Partitionseliminierung funktioniert (da für die neue Tabelle, die wir erstellt haben, keine Suchvorgänge auftreten):
Ausführungsplan:
Zu diesem Zeitpunkt müssen Sie einige Änderungen an Ihrer Anwendung vornehmen:
IDENTITY
Werte in den zugrunde liegenden Tabellen verwenden. Partitionierte Ansichten lassen dies nicht zu , daher müssen Sie in diesem Szenario Datensätze direkt in die neue Tabelle einfügen.SELECT
Abfragen (die auf die alte Tabelle verweisen) so an, dass sie auf die partitionierte Ansicht verweisen. Alternativ können Sie die alte Tabelle umbenennen (z. B. TableName_Old) und die Ansicht als Namen der alten Tabellen erstellen (z. B. TableName). Wie ausgefallen Sie hierher kommen möchten, liegt ganz bei Ihnen.Neue Datensätze in die neue Tabelle
Zu diesem Zeitpunkt sollten neue Datensätze in die neue Tabelle eingefügt werden. Ich werde dies simulieren, indem ich Folgendes ausführe:
Auch hier ist mein Identity Seed so konfiguriert, dass keine ID-Konflikte zwischen den beiden Tabellen auftreten. Die
CHECK CONSTRAINTS
auf beiden Tabellen sollten dies ebenfalls erzwingen. Lassen Sie uns bestätigen, dass die Partitionseliminierung immer noch stattfindet:Ausführungspläne:
Beachten Sie, dass die meisten Abfragen wahrscheinlich beide Tabellen umfassen. In diesen Szenarien können wir die Partitionseliminierung zwar nicht nutzen, die Abfragepläne sollten jedoch so optimal wie möglich bleiben, mit dem Vorteil, dass Sie Ihre zugrunde liegenden Abfragen nicht neu schreiben müssen (wenn Sie die Ansicht gleich benennen möchten) wie dein alter Tisch).
Was nun?
Nun, das hängt ganz von dir ab. Wenn die aktuellen Rekorde niemals verschwinden und Sie mit der Leistung von Partitioned View zufrieden sind, gießen Sie ein festliches Bier ein, weil Sie fertig sind. Huzzah!
Wenn Sie die alte Tabelle in der neuen Tabelle konsolidieren möchten, müssen Sie Wartungsfenster auswählen, in denen die nächste Reihe von Vorgängen ausgeführt werden soll. Grundsätzlich werden Sie die Einschränkungen für die Tabellen löschen (wodurch die Partitionseliminierungskomponente der partitionierten Ansicht beschädigt wird), Ihre neuesten Datensätze von der alten Tabelle in die neue Tabelle kopieren und diese Datensätze aus der alten Tabelle löschen. und aktualisieren Sie dann die Einschränkungen (damit die partitionierte Ansicht die Partitionseliminierung erneut nutzen kann). Aufgrund des Datenvolumens in den vorhandenen Tabellen müssen Sie möglicherweise einige Runden dieses Prozesses durchlaufen, um alles zu konsolidieren. Diese Schritte sind wie folgt zusammengefasst:
Wenn möglich, testen Sie dies in einer Umgebung ohne Produktion. Ich kann Tests in der Produktion nicht gutheißen. Hoffentlich hilft diese Antwort, und wenn Sie Fragen haben, können Sie gerne einen Kommentar schreiben, und ich werde mein Bestes tun, um mich schnell bei Ihnen zu melden.
quelle