enhancement
major
minor
defect
critical
major
minor
major
#30148
RecollateStringColumnsProcessor: ANALYZE nach dem Umstellen der Collation ausführen (PostgreSQL)
Beobachtung: Nach einer Migration mit dem RecollateStringColumnsProcessor auf einem großen PostgreSQL-Datenstand laufen Anfragen, die vorher schnell waren, in einen Timeout (RequestTimeoutException nach 30 s). Nach einem ANALYZE laden dieselben Ansichten wieder ohne Timeout. Ein REINDEX war dafür nicht nötig.
Ursache: Der Prozessor setzt auf PostgreSQL pro Spalte ALTER TABLE .. ALTER COLUMN .. TYPE .. COLLATE "tl_ci" ab (PostgreSQLHelper.appendChangeColumnType). Dabei verwirft PostgreSQL die Spaltenstatistiken (pg_statistic). Der PostgreSQL Query Planner arbeitet danach mit Standardschätzungen, bis Autovacuum die Tabellen analysiert hat. Die Indexes der Spalte werden von ALTER TYPE selbst neu aufgebaut.
Vorschlag: RecollateStringColumnsProcessor führt nach den ALTER-Anweisungen selbst ANALYZE aus (für die geänderten Tabellen oder datenbankweit), damit jede migrierende Anwendung abgedeckt ist. Nur für Dialekte, bei denen supportsColumnCollation() gilt.
Weitere Auffälligkeit: Der Prozessor fängt jede SQLException ab und loggt nur "Failed to re-collate string columns". Eine fehlgeschlagene Umstellung bleibt dadurch unbemerkt. Besser wäre, die Migration abzubrechen oder die Fehler am Ende zusammenzufassen.
Workaround bis dahin: ein eigener sql-Schritt mit ANALYZE; am Ende der Migration (je ein Skript für postgresql und h2).
Lösung
- Der vorhandene Dialekt-Hook DBHelper.analyzeTable(Statement, String) (bisher für MySQL und Oracle, genutzt von SecurityStorage.optimize()) wird für PostgreSQL (ANALYZE "T") und H2 (ANALYZE TABLE "T") implementiert. Daneben meldet supportsAnalyzeTable(), ob ein Dialekt Statistiken auf diesem Weg auffrischt.
- RecollateStringColumnsProcessor analysiert nach den ALTER-Anweisungen genau die Tabellen, deren Spalten er umgestellt hat (nicht datenbankweit), und protokolliert jede analysierte Tabelle.
- Der AlterColumnProcessor analysiert ebenso die Tabellen, deren Spaltentyp er geändert hat (new-type, db-type, db-size, db-precision, binary). Das Analysieren liegt dafür gemeinsam in MigrationUtil.analyzeTables(...). Umbenennen und Ändern der Pflichtangabe betrifft das nicht.
- Fehler: Eine fehlgeschlagene Umstellung wird weiterhin als Fehler protokolliert; das lässt die Migration am Ende scheitern (MigrationService prüft das Protokoll mit checkErrors()), sie bleibt also nicht unbemerkt. Die Meldung nennt jetzt Tabelle und Spalte; nach dem ersten Fehler stoppt der Prozessor (auf PostgreSQL ist die Transaktion danach ohnehin abgebrochen).
- Der Workaround mit einem eigenen ANALYZE-Skript ist damit nicht mehr nötig.