PostgreSQL Performance Scripts
PostgreSQL Performance Scripts
Query Performance, Index Usage, Cache Efficiency, Table Activity, pg_stat_statements & Execution Plans
Introduction
PostgreSQL performance troubleshooting requires visibility into query execution, table access patterns, indexes, buffer usage, temporary-file activity, statistics, database workload, and resource-intensive SQL statements.
This page provides practical PostgreSQL DBA scripts for identifying performance problems and collecting evidence before configuration changes or query-tuning decisions are made.
Contents
1. Sequential vs Index Scans 2. Unused Index Candidates 3. Index Usage Ratio 4. Database Cache Hit Ratio 5. Table Cache Hit Ratio 6. Tables with Dead Tuples 7. Temporary File Usage 8. Largest Tables and Indexes 9. Currently Long-Running Queries 10. Top Queries with pg_stat_statements 11. EXPLAIN Query Plan 12. EXPLAIN ANALYZE with Buffers 13. Check Table Statistics Freshness 14. Important Performance Settings1. Sequential vs Index Scans
This query provides a high-level view of sequential and index scan activity for user tables.
2. Unused Index Candidates
Indexes with no recorded scans may be candidates for investigation because indexes consume storage and add maintenance overhead to INSERT, UPDATE, DELETE, VACUUM, backup, and recovery operations.
idx_scan = 0.
Statistics may have been reset recently, the index may support infrequent workloads,
or it may enforce a unique or primary-key constraint. Review the complete workload
and index definition first.
3. Index Usage Ratio
The following query provides a simple table-level comparison between sequential and index scans.
Use this as an investigation aid rather than a performance target. Some tables legitimately benefit from sequential scans.
4. Database Cache Hit Ratio
The cache hit ratio compares blocks served from PostgreSQL shared buffers with blocks that PostgreSQL had to request from the operating system.
5. Table Cache Hit Ratio
A table-level cache view can help identify relations generating significant physical block reads.
6. Tables with Dead Tuples
High dead-tuple accumulation can increase table size and contribute to additional I/O. It may indicate that autovacuum requires investigation.
7. Temporary File Usage
Large sorts, hashes, and other operations can spill to temporary files when their memory requirements exceed available working memory.
work_mem globally because temporary files
are being created. work_mem can be consumed by multiple operations
inside many concurrent sessions, so aggressive settings can create memory pressure.
8. Largest Tables and Indexes
Large relations are often the most important candidates when investigating storage growth, maintenance duration, query I/O, and index overhead.
9. Currently Long-Running Queries
The following example identifies currently active statements that have been running for more than one minute.
10. Top Queries with pg_stat_statements
The pg_stat_statements extension provides aggregated planning and
execution statistics for normalized SQL statements and is one of the most useful
PostgreSQL query-performance tools.
Create the Extension
Queries Consuming the Most Total Execution Time
Queries with Highest Mean Execution Time
pg_stat_statements module normally needs to be loaded through
shared_preload_libraries before the extension can collect statistics.
Enabling or removing it from shared_preload_libraries requires a PostgreSQL restart.
11. EXPLAIN Query Plan
EXPLAIN displays the execution plan selected by the PostgreSQL planner
without executing the SQL statement when the ANALYZE option is not used.
Review the selected scan method, join strategy, estimated rows, costs, sorting, aggregation, and other plan nodes when investigating query behavior.
12. EXPLAIN ANALYZE with Buffers
Adding ANALYZE executes the SQL statement and returns actual execution
statistics. BUFFERS adds buffer-usage information that can help identify
I/O-heavy plan operations.
EXPLAIN ANALYZE actually executes the statement. For
INSERT, UPDATE, DELETE, MERGE,
and other statements with side effects, those effects occur unless you deliberately
protect the test.
Testing a Data-Modifying Statement Safely
13. Check Table Statistics Freshness
PostgreSQL's optimizer relies heavily on statistics. Stale or insufficient statistics can contribute to inaccurate row estimates and inefficient execution plans.
Refresh Statistics for a Table
14. Important Performance Settings
The following query provides a convenient snapshot of commonly reviewed PostgreSQL performance-related settings.
Recommended Performance Troubleshooting Workflow
| Step | Action | Purpose |
|---|---|---|
| 1 | Confirm the symptom | Separate database performance from application, network, or infrastructure issues |
| 2 | Identify expensive SQL | Find queries consuming significant total or average execution time |
| 3 | Review execution plans | Understand scans, joins, estimates, sorting, and I/O |
| 4 | Review statistics | Identify stale or insufficient planner statistics |
| 5 | Review indexes | Find missing, inefficient, duplicate, oversized, or unused candidates |
| 6 | Review memory and temp usage | Identify excessive spills or unsafe memory expectations |
| 7 | Correlate infrastructure metrics | Check CPU, memory, disk latency, IOPS, throughput, and network |
| 8 | Test one change at a time | Make performance improvement measurable and reversible |
Production Performance Checklist
- Establish normal workload and performance baselines.
- Identify high-impact SQL using workload statistics.
- Review execution plans before changing indexes or configuration.
- Compare estimated rows with actual rows in execution plans.
- Monitor sequential and index scan patterns.
- Review unused indexes only across a representative workload window.
- Monitor cache behavior and physical I/O.
- Monitor temporary-file generation.
- Review dead tuples and autovacuum effectiveness.
- Monitor table and index growth.
- Ensure optimizer statistics are sufficiently current.
- Correlate PostgreSQL activity with CPU, memory, disk, and network metrics.
- Load-test significant tuning changes before production deployment.
- Record before-and-after performance measurements.
- Maintain a rollback plan for significant configuration or schema changes.
Key Takeaways
- Sequential scans are not automatically performance problems.
- An index showing zero scans should be investigated rather than immediately dropped.
- Cache-hit ratios require workload context and should not be treated as universal targets.
- Temporary file activity can help identify memory-intensive SQL operations.
- Dead tuple accumulation may indicate that VACUUM activity requires investigation.
pg_stat_statementsprovides valuable aggregated query-performance information.EXPLAINshows the planner's estimated execution strategy.EXPLAIN ANALYZEexecutes the SQL statement and adds actual execution statistics.- Accurate planner statistics are critical for good PostgreSQL execution plans.
- PostgreSQL configuration tuning should be workload-specific and evidence-driven.
Conclusion
PostgreSQL performance tuning is not about finding one setting or creating indexes for every slow query. Effective tuning begins with understanding the workload, identifying SQL statements responsible for significant resource consumption, and analyzing why PostgreSQL selected a particular execution strategy.
Views such as pg_stat_activity, pg_stat_database,
pg_stat_user_tables, and pg_stat_user_indexes,
combined with pg_stat_statements and execution-plan analysis,
provide DBAs with the evidence required for structured troubleshooting.
The safest approach is to establish a baseline, identify the real bottleneck, make one measurable change at a time, validate the improvement under realistic workload conditions, and maintain a rollback path for significant changes.
Comments
Post a Comment