Skip to content

DB index, and table bloat #507

Description

@illume

Current situation

There are issues with database index and table size bloat. Leading to service slowdown, and the database running out of resources (memory) and downtime.

What we know

  • Without the REINDEX, The index are bloating from 2x to 7x the size it should be over several days. Note, no autovaccuum or autoanalyze ran.
  • autovacuum is not running (most likely because it's based on table size, rather than number of rows changed). Meaning garbage collection can't happen.
  • autoanalyze is not running(samesies as autovacuum). Meaning query statistics are not updated.
  • Cleanup script was running on boot, but didn't trigger a REINDEX after the script was changed.
  • The cleanup script with REINDEX was making several ccnew invalid transient index which were using up a lot of resources. After removing the REINDEX and VACUUM ANALYZE from the cleanup script, no new ccnew index were made. This confirms the REINDEX was creating them. https://www.postgresql.org/docs/13/sql-reindex.html
  • PostgreSQL 13 is available on RDS (we are using 12). This has index size improvements via deduplication.
  • PostgreSQL 14 is not on AWS yet. This has autovacuum improvements on delete.
  • There are index size improvements on a staging server when it was updated to pg 13.13 from 12.x and REINDEX'd. See pg 13 release notes. "Users upgrading with pg_upgrade will need to use REINDEX to make an existing index use this feature."
  • auto vacuum and auto analyze threshold changes are enough to stop the table bloat, and significantly reduce the index bloat (from 10x to 2x).

What we don't know.

  • Something else may be creating invvalid *ccnew index (I don't think we have logging to find out what did this)
    logging says the creation script ran, but with the REINDEX commented out. It could be that a REINDEX was still running from before the script stopped. Because reindexing concurrently can run for quite a long time.
  • We don't know for sure what is blocking REINDEX on some tables. Possibly the vacuum analyze ran in the older script... or something else. We could confirm if the VACUUM ANALYZE is stopping the REINDEX by running the original cleanup script on a staging server. [ED: this does not reproduce the issue]
  • We can monitor the progress of a REINDEX with https://www.postgresql.org/docs/current/progress-reporting.html#CREATE-INDEX-PROGRESS-REPORTING
    • pg_stat_progress_create_index view and columns (lockers_total, lockers_done and current_locker_pid)
      select pid,
      usename,
      pg_blocking_pids(pid) as blocked_by,
      query as blocked_query
      from pg_stat_activity
      where cardinality(pg_blocking_pids(pid)) > 0;
  • We haven't looked at if there are row based locks held. https://www.postgresql.org/docs/9.6/pgrowlocks.html Probably not necessary until we have confirmed the other issues.
  • If there are app db connection leaks, or long running transactions locking rows/tables/index. Need to deploy the nebraska memory leak statistics PR backend: Expose db connection metrics #511

Things we could do

  • cleanup script was running on boot
  • reindex and vacuum commented out and reordered to put ANALYZE at top.
  • Merge pin PostgreSQL version to 13.3, rather than latest. So we know which version we are testing. Makefile, backend: Fix pg-version pin #506
  • Merge the DB API fixes PR: Db API fixes #500 Even though we are not yet sure that the app is blocking the REINDEX from running, they are none the less problems.
  • Check the index size on pg 13.x upgraded from 12.x after applying a REINDEX to tables. [ED: this gives significant index size savings on several index after upgrading to 13 and running a REINDEX].
  • Create migration to adjust the autovacuum/autoanalyze on affected tables to be row based rather than percentage based. This would then mean other nebraska databases are covered to also have autovacuum and autoanalyze run. Test on a staging server. Why a migration script? Because the issue would affect all Nebraska users. DB Autovacuum, and Autoanalyze thresholds #508
  • We could confirm if the VACUUM ANALYZE is stopping the REINDEX by running the original cleanup script on staging data(make sure data is actually being deleted). We run the check_postgres commands before and after the script is run. Also monitor the pg_stat_progress_create_index table during the REINDEX. [ED: it does not cause this issue except when run against a server with traffic]
  • Try to reproduce generating index bloat, and getting the AUTO VACUUM and AUTO ANALYZE to run with changed thresholds. Perhaps use updateservicectl locally to generate traffic and monitor for bloat with check_postgres --action bloat.
  • Log app level connection pool stats. This will let us know if there are app db connection leaks, or long running connections blocking operations. backend: Expose db connection metrics #511
  • An alert for when there is index bloat, or when autoanalyze and autoanalyze is not being run, and also for when there are invalid transient index (ccnew etc). Perhaps using check_postgres.
  • deploy app db connection stats and analyze results

Autovacuum and Index bloat articles

Some resources about index bloat and adjusting Auto Vacuum settings.

check_postgres

check_postgres can be used to check the status of the database index bloat and when garbage collection is happening (or not).

sudo apt-get install check-postgres

check_postgres --dbuser=postgres --dbpass=nebraska --host=localhost --port=5432 --dbname=nebraska --action=bloat 

check_postgres --dbuser=postgres --dbpass=nebraska --host=localhost --port=5432 --dbname=nebraska --action=last_autovacuum 

check_postgres --dbuser=postgres --dbpass=nebraska --host=localhost --port=5432 --dbname=nebraska --action=last_autoanalyze 

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions