pg-slow-query-diagnosis — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pg-slow-query-diagnosis (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill guides systematic diagnosis and optimization of slow queries in PostgreSQL databases using the pgtuner-mcp server tools.
Use this skill when the user:
pg_stat_statements dataBefore calling tools, the agent can read lightweight resources for quick context:
pgtuner://docs/tools -- Full tool reference documentationpgtuner://docs/workflows -- Recommended workflow patternspgtuner://query/{query_hash}/stats -- Detailed stats for a specific query by queryid (from get_slow_queries output)pgtuner://table/{schema}/{table_name}/stats -- Quick table statistics without running the full toolpgtuner://table/{schema}/{table_name}/indexes -- Indexes on a specific tableThis skill corresponds to the `diagnose_slow_queries` MCP Prompt and partially to `query_tuning`. If the user triggers either prompt, follow this skill's workflow.
DATABASE_URIpg_stat_statements extension (check availability early -- if missing, tool will return an error)hypopg extension for hypothetical index testingpglast library on the server for SQL parsing in index recommendationsBefore starting the workflow, verify extension availability:
get_slow_queries returns an error about pg_stat_statements, inform the user it must be enabled and provide setup instructions.manage_hypothetical_indexes with action: "check" to verify HypoPG is available. If not, skip Step 4 and rely on heuristic recommendations.User reports slow queries
|
+--> User has a SPECIFIC query?
| YES --> Skip Step 1, go directly to Step 2 (analyze_query)
| NO --> Start with Step 1 (get_slow_queries)
|
+--> Step 1 returns 0 results?
| --> Check if pg_stat_statements was recently reset
| --> ASK user: "pg_stat_statements has limited data.
| Can you provide a specific query, or should we wait
| for more workload data to accumulate?"
|
+--> Step 2 shows temp_blks_written > 0?
| YES --> work_mem issue. Go to Step 6 (I/O) before indexes.
| NO --> Continue to Step 3 (index recommendations)
|
+--> Step 3 shows < 10% improvement from indexes?
| YES --> Query structure may be the issue.
| Redirect to pg-query-rewrite skill.
| NO --> Continue to Step 4 (verify with HypoPG)
|
+--> Step 2 shows row estimate mismatch > 10x?
YES --> Run ANALYZE on the table FIRST, then re-check
NO --> Continue with index recommendationsFollow these steps in order. At each step, analyze the output before proceeding.
Call the get_slow_queries tool to retrieve the most expensive queries:
Tool: get_slow_queries
Parameters:
limit: 10 # Start with top 10
min_calls: 5 # Focus on queries called frequently enough to matter
order_by: mean_time # Sort by average execution timeAlso check for over-fetching queries (returning too many rows):
Tool: get_slow_queries
Parameters:
limit: 10
min_calls: 5
order_by: rows # Find queries returning the most rowsWhat to look for:
mean_time (> 100ms warrants investigation)total_time (high total even if individual calls are fast)rows returned vs actual need (over-fetching -- use order_by: rows)shared_blks_hit / (shared_blks_hit + shared_blks_read) cache hit ratiotemp_blks_written > 0 (spilling to disk -- work_mem issue)Decision point: If no slow queries are found, check if pg_stat_statements has been recently reset. Suggest the user wait for workload data to accumulate, or ask them to provide a specific query.
Cross-reference with resources: For any interesting queryid found, read pgtuner://query/{queryid}/stats for deeper per-query statistics without re-running the tool.
For each problematic query identified in Step 1, run EXPLAIN ANALYZE:
Tool: analyze_query
Parameters:
query: "<the slow query>"
analyze: true # Execute the query to get actual timing
buffers: true # Show buffer usage (I/O information)
settings: true # Show GUC settings that affect the plan
verbose: false # Keep output readable
format: "text" # Human-readable indented planThe settings: true parameter reveals if session-level settings (e.g., modified work_mem) affect the plan. The format: "text" produces the classic readable plan; use format: "json" for structured programmatic analysis when needed.
What to look for in the execution plan:
actual rows differs from estimated rows by 10x or more, statistics are stale (run ANALYZE)external merge): Increase work_mem or add an index for the sort keywork_memPresent findings as a table:
| Issue | Location in Plan | Impact | Recommended Fix |
|---|---|---|---|
| Sequential scan | Seq Scan on orders | High - 2.3M rows | Create index on filter columns |
| Row estimate mismatch | ... | Medium | Run ANALYZE on table |
Use the index advisor to find optimization opportunities:
Tool: get_index_recommendations
Parameters:
workload_queries: ["<query1>", "<query2>"] # The slow queries from Step 1
max_recommendations: 10
min_improvement_percent: 10
include_hypothetical_testing: trueWhat to look for:
For the most promising index recommendations, verify using HypoPG:
Tool: explain_with_indexes
Parameters:
query: "<the slow query>"
hypothetical_indexes:
- table: "orders"
columns: ["customer_id", "created_at"]
index_type: "btree"
analyze: false # Use false for hypothetical testingWhat to look for:
For tables involved in slow queries, check their maintenance status:
Tool: get_table_stats
Parameters:
table_name: "<table_name>"
schema_name: "public"
include_indexes: trueWhat to look for:
VACUUMlast_analyze is old): Run ANALYZEIf buffer/IO issues were found in the execution plan:
Tool: analyze_disk_io_patterns
Parameters:
analysis_type: "all"
top_n: 20What to look for:
work_mem)Present the final diagnosis as:
Brief overview of findings (2-3 sentences).
Numbered list of urgent issues with specific remediation SQL.
Prioritized list with:
Any postgresql.conf changes that would help (e.g., work_mem, effective_cache_size).
| Symptom | Likely Cause | Solution |
|---|---|---|
| Seq Scan on large table | Missing index | CREATE INDEX on WHERE/JOIN columns |
| Row estimate 1 vs actual 50000 | Stale statistics | ANALYZE table_name |
| Sort Method: external merge | work_mem too low | SET work_mem = '256MB' (session) |
| Nested Loop (actual loops=10000) | Bad join strategy | Check join column indexes, statistics |
| Hash Batches: 16 | work_mem too low for hash | Increase work_mem |
| Bitmap Heap Scan (lossy) | Index not selective | Consider composite index |
After applying any fix, always verify:
analyze_query on the slow query to confirm the plan now uses the new index and timing improved.analyze_query to confirm row estimates are now accurate.buffers: true output).pg-query-rewrite skillpg-index-optimization skillpg-config-tuning skillpg-io-deep-dive skillpg-bloat-analysis skill| Feature | Version | Impact on This Workflow |
|---|---|---|
pg_stat_statements total_exec_time | PG13+ (renamed from total_time) | Column name may differ |
compute_query_id setting | PG14+ | Required for queryid in pg_stat_statements |
pg_stat_statements.track_planning | PG13+ | Enables planning time tracking |
| CTE inlining | PG12+ | Non-recursive CTEs may be optimized differently |
| Memoize plan node | PG14+ | Improves nested loop performance |
| Incremental sort | PG13+ | Optimizer may choose different sort strategies |
analyze_query with analyze: true actually executes the query. Use caution with INSERT/UPDATE/DELETE statements (they are wrapped in READ ONLY transaction for safety).explain_with_indexes before applying in production.pg_stat_statements data is sparse, ask the user to collect more workload data first.PGTUNER_EXCLUDE_USERIDS environment variable can filter out monitoring user queries from get_slow_queries results. Suggest configuring it if internal monitoring queries pollute the results.get_slow_queries, get_table_stats, analyze_disk_io_patterns) are read-only.analyze_query with analyze: true executes the query but wraps it in BEGIN TRANSACTION READ ONLY / ROLLBACK.explain_with_indexes creates temporary HypoPG indexes that exist only in the session and are never persisted.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.