enhancement
major
minor
defect
critical
major
minor
major
#30148
RecollateStringColumnsProcessor: Run ANALYZE after changing the collation (PostgreSQL)
Observation: After a migration using the RecollateStringColumnsProcessor on a large PostgreSQL database, queries that were previously fast now time out (RequestTimeoutException after 30 seconds). After running ANALYZE, the same views load again without timing out. A REINDEX was not necessary for this.
Cause: The processor applies an ALTER TABLE .. ALTER COLUMN .. TYPE .. COLLATE "tl_ci" change to each column in PostgreSQL (PostgreSQLHelper.appendChangeColumnType). In doing so, PostgreSQL discards the column statistics (pg_statistic). The PostgreSQL query planner then uses default estimates until Autovacuum has analyzed the tables. The column’s indexes are rebuilt by the `ALTER TYPE ` statement itself.
Suggestion: RecollateStringColumnsProcessor should execute ANALYZE itself after the ALTER statements(for the modified tables or database-wide) to ensure that every migrating application is covered. Only for dialects where supportsColumnCollation() applies.
Another issue: The processor catches every SQLException and logs only "Failed to re-collate string columns." As a result, a failed migration goes unnoticed. It would be better to abort the migration or summarize the errors at the end.
Workaround until then: a separate SQL step with ANALYZE at the end of the migration (one script each for PostgreSQL and H2).
Solution
- The existing dialect hook DBHelper.analyzeTable(Statement, String) (previously used for MySQL and Oracle by SecurityStorage.optimize()) is implemented for PostgreSQL (ANALYZE "T") and H2 (ANALYZE TABLE "T"). In addition, ` supportsAnalyzeTable()` indicates whether a dialect refreshes statistics in this way.
- RecollateStringColumnsProcessor analyzes, following the ALTER statements, only those tables whose columns it has converted (not database-wide) and logs each analyzed table.
- The AlterColumnProcessor also analyzes the tables whose column types it has changed (new-type, db-type, db-size, db-precision, binary). The analysis is handled collectively in ` MigrationUtil.analyzeTables(...)`. Renaming and changing the required parameter do not affect this.
- Error: A failed conversion is still logged as an error; this causes the migration to fail in the end (MigrationService checks the log with checkErrors()), so it does not go unnoticed. The message now specifies the table and column; after the first error, the processor stops (on PostgreSQL, the transaction is aborted anyway at that point).
- The workaround using a custom ANALYZE script is therefore no longer necessary.