Slow query performance investigation

warningProactive Health

Identifying and optimizing queries causing performance degradation through execution plan analysis and indexing

Prompt: Several of my PostgreSQL queries have gotten significantly slower over the past month. Help me identify the top offenders and determine whether this needs new indexes, query rewrites, or updated table statistics.

With vs Without Schema

Same prompt, same model (claude-sonnet-4-5-20250929) — the only difference is whether Schema's knowledge graph was available.

Tokens
9,717vs1,187
Latency
2.2mmsvs31.7sms
Turns
19vs14
Tool Calls
11vs5
Schema Calls
0vs1
Response
2,129 charsvs992 chars
Evaluation
Without Schema
B+
vs
With Schema
D
The response without Schema delivers a comprehensive PostgreSQL performance toolkit with six SQL scripts directly addressing the question - identifying slow queries, missing indexes, stale statistics, table bloat, and lock contention. It provides specific commands to run and clear guidance on interpreting results. The response with Schema discovers an MCP server with PostgreSQL monitoring capabilities but only requests permission to use it, providing zero actionable guidance. The without-Schema approach would immediately help diagnose the performance degradation, while the with-Schema response offers no concrete next steps.
Without Schema
11 tool calls
I'll help you identify and fix those slow PostgreSQL queries. Let me start by exploring your environment to see what we're working with. I'll create a comprehensive PostgreSQL performance analysis toolkit for you. This will help identify slow queries, missing indexes, and statistics issues. I've created a comprehensive PostgreSQL performance analysis toolkit for you. Here's what it includes: ## **Files Created:** 1. **`analyze_slow_queries.sql`** - Main analysis script that identifies: - Top 20 slowest queries by total time - Queries with highest average execution time - Queries with variable/inconsistent performance - Tables missing indexes (sequential scans on large tables) - Tables with outdated statistics - Unused indexes you can remove - Table bloat estimates - Lock contention issues - Cache hit ratios - Long-running queries 2. **`analyze_specific_query.sql`** - Deep dive into a single slow query with EXPLAIN ANALYZE 3. **`fix_statistics.sql`** - Generates ANALYZE commands for tables needing statistics updates 4. **`run_analysis.sh`** - Convenient shell script to run the analysis 5. **`enable_pg_stat_statements.sql`** - One-time setup for query tracking 6. **`README.md`** - Complete guide with usage instructions and fixing common issues ## **How to Use:** ```bash # 1. Make script executable chmod +x run_analysis.sh # 2. Run the analysis ./run_analysis.sh your_database localhost 5432 postgres # 3. Save to file for review ./run_analysis.sh your_database > performance_report.txt ``` ## **What to Look For:** The analysis will immediately show you: - **Queries consuming the most time** - your top optimization targets - **Missing indexes** - tables doing full scans when they shouldn't - **Stale statistics** - causing PostgreSQL to choose bad query plans - **Bloated tables** - needing VACUUM Based on the results, you'll know whether you need **indexes** (analysis #4), **statistics updates** (analysis #5), or **query rewrites** (analysis #1-3). Would you like me to explain any specific part of the toolkit or help you interpret results once you run it?
With Schema
5 tool calls1 Schema
I'll help you identify and optimize those slow PostgreSQL queries. Let me start by exploring what we have in this directory. I can see you have a Schema.ai MCP server configured. This appears to be a database schema and query analysis tool. Let me access these tools to help identify your slow queries. Perfect! Now let me search for PostgreSQL query performance insights and metrics to help identify your slow queries. I need your permission to access the Schema.ai tools to analyze your PostgreSQL performance. Once you approve, I'll be able to: 1. **Identify slow query patterns** - Find metrics and insights about query performance degradation 2. **Analyze index usage** - Determine if missing or unused indexes are causing slowdowns 3. **Check statistics** - See if stale table statistics need updating 4. **Review query plans** - Get guidance on query optimization techniques Please approve the tool access, and I'll immediately start investigating your PostgreSQL performance issues.

Agent Playbook

When an agent encounters this scenario, Schema provides these diagnostic steps automatically.

When investigating slow PostgreSQL queries, start by identifying the top offenders based on total execution time (not just per-query duration), then check for stale statistics which are the most common and easiest fix. Next, analyze execution plans to understand what's actually happening, look for missing indexes based on sequential scan patterns, and finally investigate table bloat and memory pressure if the previous steps don't resolve the issue.

1Identify queries with highest total execution time
Query pg_stat_statements ordered by `stat_statements_seconds` (total_exec_time) DESC, not just mean execution time. A query running 50ms but called 10,000 times per hour (139 hours total) is far worse than a 5-second query called once. Look at the `stat_statements_calls` count alongside duration — high call frequency with moderate latency usually offers the best optimization ROI. Focus on the top 5-10 queries by total time for the rest of your investigation.
2Check for stale statistics on affected tables
Check `last-analyze` timestamps and `n_mod_since_analyze` counts in pg_stat_user_tables for the tables used by your slow queries. If `n_mod_since_analyze` shows thousands or millions of rows modified since the last ANALYZE, or `last-analyze` is days/weeks old, your query planner is making decisions on outdated statistics, which can cause exponentially worse query plans. Run ANALYZE on those tables immediately and retest — this is the most common culprit and takes seconds to fix.
3Analyze execution plans with EXPLAIN ANALYZE
Run EXPLAIN (ANALYZE, BUFFERS, VERBOSE) on your top offending queries to see the actual execution plan and I/O patterns. Look for sequential scans on large tables, nested loops with high row counts, and hash joins that spill to disk. Compare `postgresql.blk_read_time` — if block read time is high, you're I/O bound. Pay attention to the planner's row count estimates versus actual rows — large discrepancies confirm stale statistics or missing WHERE clause selectivity.
4Look for missing indexes via sequential scan patterns
Compare `postgresql.sequential_scans` to `postgresql.index.scans` at the table level, and check `postgresql.seq_rows_read` versus `postgresql.index.rows_fetched`. If you see high sequential scan counts on tables with >100K rows, especially in your top slow queries, you likely need indexes. Cross-reference with EXPLAIN output — look for 'Seq Scan' nodes where you expected index usage. Create indexes on columns used in WHERE clauses, JOIN conditions, and ORDER BY for those queries.
5Check table bloat for unavoidable sequential scans
If sequential scans are legitimate (small tables or queries that need full scans), check `n_dead_tup` to identify table bloat. Bloat increases I/O cost linearly since PostgreSQL reads dead tuples during scans even though they're not returned. If `n_dead_tup` is >20% of live tuples and `postgresql.blk_read_time` is elevated, run VACUUM on those tables or tune autovacuum to run more aggressively. This is especially important after bulk operations or heavy UPDATE/DELETE workloads.
6Check for memory pressure via temp file usage
Look at `postgresql.temp_bytes` to identify queries spilling sorts, hashes, or aggregations to disk due to insufficient work_mem. If temp file usage is high (megabytes to gigabytes per query), your queries are memory-starved. Either increase work_mem (carefully — it's per-operation, not per-connection) or rewrite queries to reduce sort/hash operations. This is common with large JOINs, GROUP BY, or ORDER BY on unindexed columns.

Technologies

Related Insights

Slow PostgreSQL queries with high execution time or IO consumption
warning
Slow queries consuming excessive total execution time degrade performance
warning
Slow queries exceed execution time threshold
warning
Slow query performance degrades from milliseconds to seconds
warning
Inefficient query plans cause production slowdowns despite dev performance
warning
Missing or ineffective indexes cause sequential scans on large tables
warning
High sequential scan count may indicate missing indexes requiring query optimization
warning
Query performance degrading over time due to stale statistics
warning
need for index creation
prerequisite
Stub insight created from scenario discovery hint: need for index creation
Stale statistics cause inefficient query plans with exponentially worse performance
prerequisitewarning
need for query optimization
prerequisite
Stub insight created from scenario discovery hint: need for query optimization
Table bloat increases sequential scan cost linearly
supporting_evidencewarning
need for ANALYZE
supporting_evidence
Stub insight created from scenario discovery hint: need for ANALYZE
Stale statistics cause poor query plans
prerequisitewarning
query plan regression
prerequisite
Stub insight created from scenario discovery hint: query plan regression

Relevant Metrics

Monitoring Interfaces

PostgreSQL Prometheus Exporter (pg_exporter)
PostgreSQL Datadog Integration
PostgreSQL Native
PostgreSQL OpenTelemetry Receiver
PostgreSQL Datadog