pg-index-optimization — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited pg-index-optimization (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 comprehensive index analysis and optimization for PostgreSQL databases using pgtuner-mcp tools, including HypoPG hypothetical index testing.
Use this skill when the user:
pgtuner://docs/tools -- Full tool reference documentationpgtuner://table/{schema}/{table_name}/indexes -- Quick view of existing indexes on a table (lightweight)pgtuner://table/{schema}/{table_name}/stats -- Table statistics for contextpgtuner://query/{query_hash}/stats -- Per-query stats to understand which queries benefit from indexesThis skill corresponds to the `index_optimization` MCP Prompt. If the user triggers that prompt, follow this skill's workflow.
DATABASE_URIpg_stat_statements extension for workload analysishypopg extension for hypothetical index testingpgstattuple extension for index bloat analysisBefore starting, check extension availability:
manage_hypothetical_indexes with action: "check" to verify HypoPG. If unavailable, skip Phase 3 (hypothetical testing) and rely on heuristic-based recommendations.analyze_index_bloat returns an error about pgstattuple, note that bloat measurements will be estimated rather than exact.User asks about indexes
|
+--> "Which indexes can I drop?"
| --> Start with Phase 1 (cleanup), focus on Step 1.1
|
+--> "What indexes should I create?"
| --> Start with Phase 2 (missing indexes)
|
+--> "Comprehensive index review"
| --> Follow all 4 phases in order
|
+--> "Test a specific index idea"
| --> Skip to Phase 3 (hypothetical testing)
|
+--> After finding unused indexes, also check:
--> Read pgtuner://table/{schema}/{table}/indexes for quick context
--> Cross-reference: are the "unused" indexes UNIQUE? (warn user)
--> Cross-reference: how long has the DB been up?#### Step 1.1: Find Unused Indexes
Tool: find_unused_indexes
Parameters:
schema_name: "public"
min_size_mb: 1
include_duplicates: trueWhat to analyze:
idx_a on (col1) is redundant if idx_b on (col1, col2) exists)Before recommending DROP:
SELECT pg_postmaster_start_time()pg_stat_statements was recently resetGenerate cleanup SQL:
-- DROP INDEX CONCURRENTLY avoids blocking writes
DROP INDEX CONCURRENTLY IF EXISTS schema.index_name;#### Step 1.2: Analyze Index Bloat
Tool: analyze_index_bloat
Parameters:
schema_name: "public"
min_index_size_gb: 0.1 # Lower threshold to catch more issues
min_bloat_percent: 20What to analyze:
Remediation:
-- REINDEX CONCURRENTLY (PostgreSQL 12+) avoids blocking
REINDEX INDEX CONCURRENTLY schema.index_name;#### Step 2.1: Workload-Based Recommendations
Tool: get_index_recommendations
Parameters:
max_recommendations: 10
min_improvement_percent: 10
include_hypothetical_testing: trueIf the user has specific queries to optimize:
Tool: get_index_recommendations
Parameters:
workload_queries: ["SELECT ... FROM orders WHERE ...", "SELECT ... FROM users JOIN ..."]
max_recommendations: 10
min_improvement_percent: 10
include_hypothetical_testing: true
target_tables: ["orders", "users"] # Optional: focus on specific tablesEvaluate each recommendation:
#### Step 2.2: Check Table Access Patterns
For tables flagged in recommendations:
Tool: get_table_stats
Parameters:
table_name: "<table_name>"
include_indexes: true
order_by: "seq_scans"What to analyze:
#### Step 3.1: Test Recommended Indexes
For each promising recommendation, test with HypoPG:
Tool: explain_with_indexes
Parameters:
query: "<query that will benefit>"
hypothetical_indexes:
- table: "orders"
columns: ["customer_id", "created_at"]
index_type: "btree"
unique: false
- table: "orders"
columns: ["status"]
index_type: "btree"
analyze: falseEvaluate the result:
#### Step 3.2: Advanced HypoPG Testing
For more complex scenarios, start by checking HypoPG availability:
Tool: manage_hypothetical_indexes
Parameters:
action: "check"If available, test advanced index types:
Tool: manage_hypothetical_indexes
Parameters:
action: "create"
table: "orders"
columns: ["customer_id", "created_at"]
index_type: "btree"
schema: "public"
include: ["order_total"] # Covering index for Index Only ScanEstimate the storage cost of a hypothetical index:
Tool: manage_hypothetical_indexes
Parameters:
action: "estimate_size"
table: "orders"
columns: ["customer_id", "created_at"]
index_type: "btree"Test partial indexes (index only matching rows):
Tool: manage_hypothetical_indexes
Parameters:
action: "create"
table: "orders"
columns: ["created_at"]
index_type: "btree"
where: "status = 'pending'" # Only index pending ordersTest what happens if you hide an existing index:
Tool: manage_hypothetical_indexes
Parameters:
action: "hide"
index_id: <real_index_oid>Verify which indexes are currently hidden:
Tool: manage_hypothetical_indexes
Parameters:
action: "list_hidden"List all currently created hypothetical indexes:
Tool: manage_hypothetical_indexes
Parameters:
action: "list"Then explain the query to see if performance changes:
Tool: manage_hypothetical_indexes
Parameters:
action: "explain_with_index"
query: "SELECT ... FROM orders WHERE ..."
table: "orders"
columns: ["customer_id", "created_at"]Restore hidden indexes and clean up when done:
Tool: manage_hypothetical_indexes
Parameters:
action: "reset"Compile all findings into a prioritized action plan.
| Index | Table | Size | Reason | DROP Statement |
|---|---|---|---|---|
| idx_old_status | orders | 245 MB | 0 scans in 30 days | DROP INDEX CONCURRENTLY idx_old_status; |
| Index | Table | Size | Bloat % | REINDEX Statement |
|---|---|---|---|---|
| idx_orders_date | orders | 1.2 GB | 45% | REINDEX INDEX CONCURRENTLY idx_orders_date; |
| Table | Columns | Type | Improvement | CREATE Statement |
|---|---|---|---|---|
| orders | (customer_id, created_at) | btree | 72% | CREATE INDEX CONCURRENTLY idx_orders_cust_date ON orders (customer_id, created_at); |
Present these guidelines when making recommendations:
| Use Case | Index Type |
|---|---|
| Equality and range queries (default) | btree |
| Equality-only lookups | hash |
| Full-text search | gin |
| Geometric / range data types | gist |
| Very large tables, time-series | brin |
CONCURRENTLY for CREATE/DROP/REINDEX in production to avoid blockingANALYZE table_name to update statisticspg_stat_user_tables.n_tup_ins/upd/delAfter applying index changes:
analyze_query on affected queries to confirm the plan uses the new index.analyze_query to ensure no critical query regressed. Monitor application error rates.analyze_index_bloat to confirm bloat was resolved.find_unused_indexes to confirm the new state is clean.pg-slow-query-diagnosis skillpg-query-rewrite skillpg-bloat-analysis skillpg-io-deep-dive skill| Feature | Version |
|---|---|
INCLUDE columns in indexes (covering indexes) | PG11+ |
REINDEX CONCURRENTLY | PG12+ |
| Deduplication for B-tree indexes | PG13+ |
pg_stat_progress_create_index | PG12+ |
manage_hypothetical_indexes with action: "hide" only hides the index from the planner in the current session. It does not affect other sessions or actual data.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.