Ich habe eine Frage zum ALTER TABLE
Befehl in einer wirklich großen Tabelle (fast 30 Millionen Zeilen). Eine seiner Spalten ist a varchar(255)
und ich möchte die Größe auf a ändern varchar(40)
. Grundsätzlich möchte ich meine Spalte ändern, indem ich den folgenden Befehl ausführe:
ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);
Ich habe kein Problem, wenn der Prozess sehr lang ist, aber es scheint, dass meine Tabelle während des Befehls ALTER TABLE nicht mehr lesbar ist. Gibt es einen klügeren Weg? Vielleicht eine neue Spalte hinzufügen, Werte aus der alten Spalte kopieren, die alte Spalte löschen und schließlich die neue umbenennen?
Jeder Hinweis wird sehr geschätzt! Danke im Voraus,
Hinweis: Ich verwende PostgreSQL 9.0.
postgresql
varchar
alter-table
Labynocle
quelle
quelle
resizing
Um ganz klar zu sein: Wissen Sie, dass der Tisch dadurch nicht weniger Platz einnimmt?varchar(255)
zu PostgreSQL sagen , werden 255 Bytes für einen Wert mit einer tatsächlichen Länge von 40 Bytes nicht zugewiesen. Es werden 40 Bytes (plus interner Overhead) zugewiesen. Das einzige, wasbe changed by the
ALTER TABLE` ist, ist die maximale Anzahl von Bytes, die Sie in dieser Spalte speichern können, ohne einen Fehler von PG zu erhalten.Antworten:
Eine Beschreibung dazu finden Sie unter Ändern der Größe einer Spalte in einer PostgreSQL-Tabelle, ohne Daten zu ändern . Sie müssen die Datenbankkatalogdaten hacken. Die einzige Möglichkeit, dies offiziell zu tun, ist mit ALTER TABLE. Wie Sie bereits bemerkt haben, wird durch die Änderung die gesamte Tabelle gesperrt und neu geschrieben, während sie ausgeführt wird.
Stellen Sie sicher, dass Sie den Abschnitt Zeichentypen in den Dokumenten gelesen haben, bevor Sie dies ändern. Alle möglichen seltsamen Fälle, die hier zu beachten sind. Die Längenprüfung wird durchgeführt, wenn Werte in den Zeilen gespeichert werden. Wenn Sie dort eine Untergrenze hacken, wird die Größe der vorhandenen Werte überhaupt nicht verringert. Es ist ratsam, die gesamte Tabelle nach Zeilen zu durchsuchen, deren Feldlänge nach der Änderung> 40 Zeichen beträgt. Sie müssen herausfinden, wie Sie diese manuell abschneiden können - damit Sie einige Sperren nur bei übergroßen zurücksetzen -, denn wenn jemand versucht, etwas in dieser Zeile zu aktualisieren, wird es jetzt als zu groß zurückgewiesen Es wird die neue Version der Zeile gespeichert. Heiterkeit entsteht für den Benutzer.
VARCHAR ist ein schrecklicher Typ, der in PostgreSQL nur existiert, um den damit verbundenen schrecklichen Teil des SQL-Standards zu erfüllen. Wenn Sie sich nicht für die Kompatibilität mit mehreren Datenbanken interessieren, sollten Sie Ihre Daten als TEXT speichern und eine Einschränkung hinzufügen, um ihre Länge zu begrenzen. Einschränkungen, die Sie ohne dieses Problem beim Sperren / Umschreiben von Tabellen ändern können, können mehr Integritätsprüfungen durchführen als nur die Prüfung der schwachen Länge.
quelle
In PostgreSQL 9.1 gibt es einen einfacheren Weg
http://www.postgresql.org/message-id/[email protected]
quelle
Ok, ich bin wahrscheinlich zu spät zur Party, ABER ...
Es besteht keine Notwendigkeit, die Größe der Spalte in Ihrem Fall zu ändern!
Postgres ist im Gegensatz zu einigen anderen Datenbanken intelligent genug, um nur genügend Speicherplatz für die Zeichenfolge zu verwenden (auch bei längerer Zeichenfolge wird die Komprimierung verwendet). Selbst wenn Ihre Spalte als VARCHAR (255) deklariert ist - wenn Sie Zeichenfolgen mit 40 Zeichen in speichern In der Spalte beträgt die Speicherplatznutzung 40 Byte + 1 Byte Overhead.
( http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )
Die Größenangabe in VARCHAR wird nur verwendet, um die Größe der eingefügten Werte zu überprüfen. Sie hat keinen Einfluss auf das Festplattenlayout. Tatsächlich werden VARCHAR- und TEXT-Felder in Postgres auf dieselbe Weise gespeichert .
quelle
Ich hatte das gleiche Problem beim Versuch, ein VARCHAR von 32 auf 8 zu kürzen und das zu bekommen
ERROR: value too long for type character varying(8)
. Ich möchte so nah wie möglich an SQL bleiben, da ich eine selbst erstellte JPA-ähnliche Struktur verwende, die wir je nach Wahl des Kunden möglicherweise auf ein anderes DBMS umstellen müssen (PostgreSQL ist die Standardstruktur). Daher möchte ich nicht den Trick verwenden, Systemtabellen zu ändern.Ich beendete die Verwendung der
USING
Anweisung inALTER TABLE
:Wie @raylu bemerkte,
ALTER
erhält der Tisch eine exklusive Sperre, sodass alle anderen Vorgänge verzögert werden, bis sie abgeschlossen sind.quelle
ALTER
erwirbt eine exklusive Sperre auf dem Tisch und verhindert alle anderen OperationenDas Hinzufügen einer neuen Spalte und das Ersetzen einer neuen durch eine alte Spalte, die für mich funktioniert hat, finden Sie unter redshift postgresql unter diesem Link unter https://gist.github.com/mmasashi/7107430
quelle
Hier ist der Cache der von Greg Smith beschriebenen Seite. Falls dies ebenfalls stirbt, sieht die alter-Anweisung folgendermaßen aus:
Wenn Ihre Tabelle TABLE1 ist, ist die Spalte COL1 und Sie möchten sie auf 35 Zeichen setzen (die +4 werden für Legacy-Zwecke gemäß dem Link benötigt, möglicherweise der Overhead, auf den AH in den Kommentaren verweist).
quelle
Wenn Sie die Änderung in eine Transaktion einfügen, sollte die Tabelle nicht gesperrt werden:
Das funktionierte für mich blitzschnell, einige Sekunden auf einem Tisch mit mehr als 400.000 Zeilen.
quelle
ALTER
Anweisung ändern ? Das tut es nicht.COMMIT
. Der Wrapper ist nur dann sinnvoll, wenn Sie mehr Befehle in dieselbe Transaktion einfügen möchten.Ich habe eine sehr einfache Möglichkeit gefunden, die Größe zu ändern, dh die Anmerkung @Size (min = 1, max = 50), die Teil von "import javax.validation.constraints" ist, dh "import javax.validation.constraints.Size;"
quelle
Führen Sie die folgende Änderungstabelle aus:
quelle