Ich habe Probleme, einer Tabelle eine neue Spalte hinzuzufügen.
Ich habe ein paar Mal versucht, es auszuführen, aber nach mehr als 10 Minuten habe ich beschlossen, die Abfrage wegen der Sperrzeit abzubrechen.
ALTER TABLE mytable ADD mycolumn VARCHAR(50);
Nützliche Informationen:
- PostgreSQL-Version: 9.1
- Anzahl der Zeilen: ~ 250K
- Anzahl der Spalten: 38
- Anzahl der nullbaren Spalten: 32
- Anzahl der Einschränkungen: 5 (1 PK, 3 FK, 1 EINZIGARTIG)
- Anzahl der Indizes: 1
- Betriebssystemtyp: Debian Squeeze 64
Ich fand interessante Informationen darüber, wie PostgreSQL nullfähige Spalten verwaltet (über HeapTupleHeader).
Meine erste Vermutung ist, dass MAXALIGN
HeapTupleHeader 4 Bytes lang ist, da diese Tabelle bereits 32 nullfähige Spalten mit 8 Bit enthält (nicht verifiziert, und ich weiß nicht, wie das geht).
Das Hinzufügen einer neuen nullfähigen Spalte erfordert möglicherweise eine Aktualisierung von HeapTupleHeader in jeder Zeile, um neue 8-Bit-Spalten hinzuzufügen MAXALIGN
, was zu Leistungsproblemen führen kann.
Also habe ich versucht, eine der nullbaren Spalten (die in Wirklichkeit nicht wirklich nullbar ist) zu ändern, um die Anzahl der nullbaren Spalten auf 31 zu verringern und zu überprüfen, ob meine Vermutung wahr sein könnte.
ALTER TABLE mytable ALTER myothercolumn SET NOT NULL;
Leider dauert diese Änderung auch sehr lange, mehr als 5 Minuten, so dass ich sie auch abgebrochen habe.
Haben Sie eine Vorstellung davon, was diese Leistungskosten verursachen könnte?
quelle
SET NOT NULL
nicht die Art ändern, es fügt nur eine Einschränkung - aber die Einschränkung muss geprüft gegen den Tisch, und das erfordert einen vollständigen Tabellenscan. 9.4 verbessert einige dieser Fälle, indem es schwächere Sperren verwendet, aber es ist immer noch ziemlich schwer.Antworten:
Hier gibt es einige Missverständnisse:
Die Null-Bitmap ist nicht Teil des Heap-Tupel-Headers. Pro Dokumentation:
Ihre 32 nullbaren Spalten sind aus zwei Gründen nicht verdächtig:
Die Null-Bitmap wird pro Zeile hinzugefügt , und zwar nur, wenn mindestens ein tatsächlicher
NULL
Wert in der Zeile vorhanden ist. Nullable Spalten haben keine direkte Auswirkung, nur tatsächlicheNULL
Werte. Wenn die Null-Bitmap zugewiesen ist, wird sie immer vollständig zugewiesen (alles oder nichts). Die tatsächliche Größe der Null-Bitmap beträgt 1 Bit pro Spalte, aufgerundet auf das nächste Byte . Gemäß aktuellem Quellencode:Die Null-Bitmap wird nach dem Heap-Tupel-Header zugewiesen, gefolgt von einer optionalen OID und anschließend Zeilendaten. Der Beginn einer OID oder von Zeilendaten wird
t_hoff
im Header durch angezeigt . Quellcode pro Kommentar :Nach dem Heap-Tupel-Header befindet sich ein freies Byte, das 23 Bytes belegt. Die Null-Bitmap für Zeilen mit bis zu 8 Spalten ist also effektiv ohne zusätzliche Kosten. Mit der 9. Spalte in der Tabelle werden
t_hoff
weitereMAXALIGN
(normalerweise 8) Bytes erweitert, um weitere 64 Spalten bereitzustellen. Die nächste Grenze wäre also 72 Spalten.So zeigen Sie Steuerinformationen eines PostgreSQL-Datenbankclusters (inkl.
MAXALIGN
) An, Beispiel für eine typische Installation von Postgres 9.3 auf einem Debian-Computer:Ich habe die Anweisungen in der von Ihnen zitierten Antwort aktualisiert .
ALTER TABLE
Abgesehen davon sind 250 KB wirklich nicht so viel und würden auf jedem halbwegs anständigen Computer eine Frage von Sekunden sein (es sei denn, die Zeilen sind ungewöhnlich groß) , selbst wenn Ihre Anweisung ein Umschreiben einer ganzen Tabelle auslöst (was wahrscheinlich der Fall ist, wenn ein Datentyp geändert wird). . 10 Minuten oder mehr weisen auf ein völlig anderes Problem hin. Ihre Aussage wartet höchstwahrscheinlich darauf, eine Sperre für den Tisch zu bekommen.Die wachsende Anzahl von Einträgen in
pg_stat_activity
bedeutet offenere Transaktionen - zeigt an, dass gleichzeitig (höchstwahrscheinlich) gleichzeitig auf die Tabelle zugegriffen werden muss, bis der Vorgang abgeschlossen ist.Ein paar Aufnahmen im Dunkeln
Suchen Sie nach einem möglichen Aufblähen des Tisches, versuchen Sie es mit einem sanften
VACUUM mytable
oder aggressiveren VorgangVACUUM FULL mytable
- bei dem möglicherweise dieselben Parallelitätsprobleme auftreten, da dieses Formular auch eine exklusive Sperre erhält. Sie könnten stattdessen pg_repack versuchen ...Ich würde zunächst mögliche Probleme mit Indizes, Triggern, Fremdschlüsseln oder anderen Einschränkungen untersuchen, insbesondere solche, die die Spalte betreffen. Insbesondere könnte ein beschädigter Index beteiligt sein? Probieren Sie
REINDEX TABLE mytable;
oderDROP
alle aus und fügen Sie sie anschließendALTER TABLE
in derselben Transaktion erneut hinzu .Versuchen Sie, den Befehl nachts oder immer dann auszuführen, wenn nicht viel Last vorhanden ist.
Eine Brute-Force-Methode wäre, den Zugriff auf den Server zu beenden und es dann erneut zu versuchen:
Ein Upgrade auf die aktuelle Version oder insbesondere auf die kommende Version 9.4 kann hilfreich sein, ohne dass Sie dies feststellen können . Es wurden verschiedene Verbesserungen für große Tabellen und für das Sperren von Details vorgenommen. Aber wenn in Ihrer Datenbank etwas kaputt ist, sollten Sie das wahrscheinlich zuerst herausfinden.
quelle