PostgreSQL(15 to 16) Upgrade: Solving Query Performance Issues with VACUUM ANALYZE

PostgreSQL

Hi all and merry christmas 🎄

Today was a upgrade/patch fixes day for our DevOps team 🧹 We upgraded our main PostgreSQL database from version 15 to 16. The migration process went smoothly, and everything appeared to be functioning as expected. However, shortly after, we noticed a significant degradation in query performance.

Some queries that previously executed in 60ms were now taking an alarming 16-18 seconds! While some queries performed fine, others were painfully slow. It was clear something needed immediate attention.

Debugging the Problem

Our first step was to investigate the usual suspects:

  • Indexes: We checked all table indexes to ensure they existed and appeared intact. They were all present and seemed fine.
  • Query Planner Behavior: Despite the indexes being available, the database query planner was opting for sequential scans instead of using the indexes.

This was puzzling. Why wasn’t the planner using the indexes? 🤔

When I looked up what changed from PostgreSQL 15 to 16, ChatGPT mentioned some improvements in parallel processing. This seemed a bit suspect.

Initial Attempts to Fix the Problem

We discussed the issue with our team leads and decided to try reindexing the affected tables and database using the following commands:

Reindexing Commands

-- Reindex a specific table
REINDEX TABLE table_name;

-- Reindex the entire database
REINDEX DATABASE my_database;

⭐️ Bonus – when you upgrade a database, indexes can become broken if you do not take a dump and import it. BTW we tested the upgrade scenario in our staging environment with the same version, which has as much data as production due to automation tools, everything was fine.

While reindexing helped improve performance for some queries, others were still taking an inordinate amount of time to execute. The issue persisted.

Discovering the Solution: VACUUM ANALYZE

After further investigation by our other team members, we came across a potential fix: running VACUUM ANALYZE. This command cleans up dead tuples and updates statistics that the PostgreSQL query planner relies on to make optimal decisions.

🎯 This part is essential

VACUUM ANALYZE Command

VACUUM (ANALYZE, VERBOSE);

We executed the command on our database. Here’s what happened next:

  1. Dead Tuple Cleanup: The vacuuming process removed obsolete rows, freeing up storage and improving table health.
  2. Statistics Refresh: The ANALYZE portion updated the planner statistics, enabling it to accurately estimate costs and choose indexes for queries.

The Result: Instant Improvement

Once the VACUUM ANALYZE process completed, the results were astonishing:

  • All previously slow queries were back to their original performance.
  • The query planner started using indexes correctly.

Voila! The issue was resolved.

Lessons Learned

  1. Post-Migration Maintenance: After any major PostgreSQL version upgrade, always run VACUUM ANALYZE to ensure the database planner has accurate statistics.
  2. Regular Maintenance: Schedule regular vacuuming to keep statistics up-to-date and maintain optimal performance.

Conclusion

Upgrading PostgreSQL versions can sometimes introduce unexpected performance challenges. In our case, running VACUUM ANALYZE after upgrading from version 15 to 16 was the key to resolving query performance issues.

If you’re facing similar problems after a database migration, don’t forget to include this simple yet powerful command in your troubleshooting toolkit.

Happy querying! 😊

Leave a Reply

Your email address will not be published. Required fields are marked *