ワンクリックで
db-analyze-hotpaths
Run EXPLAIN ANALYZE on common/critical queries to identify performance issues
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Run EXPLAIN ANALYZE on common/critical queries to identify performance issues
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Execute story development with selectable automation modes to accommodate different developer preferences, skill levels, and story complexity.
Set up a Kord-aligned documentation baseline (no legacy frameworks)
Create Next Story Task methodology and workflow
Validate Next Story Task methodology and workflow
advanced-elicitation methodology and workflow
No checklists needed - this task facilitates brainstorming sessions, validation is through user interaction methodology and workflow
| name | db-analyze-hotpaths |
| description | Run EXPLAIN ANALYZE on common/critical queries to identify performance issues |
| agent | architect |
| subtask | false |
Run EXPLAIN ANALYZE on common/critical queries to identify performance issues
Parameter:* mode (optional, default: interactive)
Purpose:* Definitive pass/fail criteria for task completion
Checklist:*
acceptance-criteria:
- [ ] Data persisted correctly; constraints respected; no orphaned data
type: acceptance-criterion
blocker: true
validation: |
Assert data persisted correctly; constraints respected; no orphaned data
error_message: "Acceptance criterion not met: Data persisted correctly; constraints respected; no orphaned data"
Strategy:* fallback
Common Errors:*
Error:* Connection Failed
Error:* Query Syntax Error
Error:* Transaction Rollback
queries_file (optional): Path to file with labeled queries to analyzeEnsure performance monitoring is available:
echo "Enabling performance extensions..."
psql "$SUPABASE_DB_URL" << 'EOF'
-- Enable pg_stat_statements (should already be enabled in Supabase)
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Optionally enable index_advisor (Supabase extension)
CREATE EXTENSION IF NOT EXISTS index_advisor;
SELECT 'Extensions ready' AS status;
EOF
echo "✓ Extensions enabled"
If no queries_file provided, find slowest queries from pg_stat_statements:
echo "Finding slow queries from pg_stat_statements..."
psql "$SUPABASE_DB_URL" << 'EOF'
SELECT
query,
calls,
ROUND(total_exec_time::numeric, 2) AS total_time_ms,
ROUND(mean_exec_time::numeric, 2) AS mean_time_ms,
ROUND(max_exec_time::numeric, 2) AS max_time_ms,
ROUND((100 * total_exec_time / SUM(total_exec_time) OVER ())::numeric, 2) AS pct_total_time
FROM pg_stat_statements
WHERE query NOT LIKE '%pg_stat_statements%'
AND query NOT LIKE '%pg_catalog%'
ORDER BY mean_exec_time DESC
LIMIT 20;
EOF
Ask user:
Top 20 slow queries found.
Select query numbers to analyze (comma-separated, e.g., 1,3,5):
Or type 'all' to analyze all:
For each selected query, run comprehensive analysis:
echo "Analyzing query performance..."
# CRITICAL: Always use ANALYZE, BUFFERS for complete picture
psql "$SUPABASE_DB_URL" << 'EOF'
-- Query being analyzed
\echo '=========================================='
\echo 'QUERY: {query_label}'
\echo '=========================================='
-- Option 1: EXPLAIN ANALYZE with BUFFERS (recommended)
EXPLAIN (
ANALYZE true,
BUFFERS true,
VERBOSE true,
COSTS true,
TIMING true
)
{actual_query};
\echo ''
\echo 'BUFFERS LEGEND:'
\echo ' - shared hit = blocks found in buffer cache (good)'
\echo ' - shared read = blocks read from disk (bad if high)'
\echo ' - temp read/written = temporary files (bad if present)'
\echo ''
EOF
Use index_advisor extension (Supabase-specific):
echo "Generating index recommendations..."
psql "$SUPABASE_DB_URL" << 'EOF'
-- Use index_advisor to get suggestions
SELECT *
FROM index_advisor('{actual_query}');
-- Alternative: Supabase Studio has Index Advisor UI
-- Navigate to: Query Performance Report → Select query → "indexes" tab
EOF
Identify common performance issues:
echo "Performance Issue Checklist:"
echo ""
echo "🔍 Sequential Scans:"
echo " - Look for: 'Seq Scan on table_name'"
echo " - Problem if: Large tables (>1000 rows) + filter removes many rows"
echo " - Fix: Add index on filter columns"
echo ""
echo "🔍 Row Count Mismatches:"
echo " - Compare: rows=XXXX (estimated) vs actual rows=YYYY"
echo " - Problem if: Estimate differs by >10x from actual"
echo " - Fix: ANALYZE table_name; (update statistics)"
echo ""
echo "🔍 Buffer Cache Misses:"
echo " - Look for: 'shared read' in BUFFERS output"
echo " - Problem if: High compared to 'shared hit'"
echo " - Fix: Increase shared_buffers, optimize query, add indexes"
echo ""
echo "🔍 Temporary Files:"
echo " - Look for: 'temp read' or 'temp written' in BUFFERS"
echo " - Problem: Query using disk for sorting/hashing (work_mem too small)"
echo " - Fix: Increase work_mem, optimize query, add indexes"
echo ""
echo "🔍 Nested Loops:"
echo " - Look for: 'Nested Loop' with high row counts"
echo " - Problem if: Loops=10000+ iterations"
echo " - Fix: Add indexes on join columns, consider Hash Join"
echo ""
Generate markdown report with findings:
REPORT_FILE="supabase/docs/performance-analysis-$(date +%Y%m%d%H%M%S).md"
mkdir -p supabase/docs
cat > "$REPORT_FILE" << 'MDEOF'
# Query Performance Analysis
*Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
*Database**: [redacted]
*Tool**: DB Sage db-analyze-hotpaths
---
## Executive Summary
- Queries analyzed: {count}
- Avg execution time: {avg_time}ms
- Indexes recommended: {index_count}
---
### Query 1: {query_label}
*Current Performance:**
- Mean execution time: {mean_time}ms
- Calls: {calls}
- % of total time: {pct_time}%
*EXPLAIN ANALYZE Output:**
{explain_output}
*Issues Identified:**
1. {issue_1}
2. {issue_2}
*Recommended Indexes:**
```sql
{recommended_indexes}
Expected Improvement:* {estimated_improvement}
[Repeat for each query...]
MDEOF
echo "✓ Report: $REPORT_FILE"
---
## Output
Display summary and next steps:
✅ HOT PATH ANALYSIS COMPLETE
Queries analyzed: {count} Report: supabase/docs/performance-analysis-{timestamp}.md
Key Findings:
Recommended Actions:
Index Recommendations: {list of CREATE INDEX statements}
---
### Pattern 1: User-Specific Data
```sql
-- Hot path: Get user's posts
SELECT * FROM posts WHERE user_id = 'xxx';
-- Check: Index on user_id exists?
-- Verify: USING (auth.uid() = user_id) is wrapped in SELECT for RLS performance
-- Hot path: Posts with author info
SELECT p.*, u.name
FROM posts p
JOIN users u ON p.user_id = u.id;
-- Check: Index on posts(user_id)? Index on users(id) should exist (PK)
-- Hot path: Recent published posts
SELECT * FROM posts
WHERE status = 'published'
ORDER BY created_at DESC
LIMIT 10;
-- Check: Index on (status, created_at DESC)?
-- Hot path: User post count
SELECT user_id, COUNT(*)
FROM posts
GROUP BY user_id;
-- Check: Index on user_id? Or denormalize count?
Good (Cached):*
Buffers: shared hit=100
= 100 blocks found in cache (no disk I/O)
Bad (Disk Reads):*
Buffers: shared hit=10 read=990
= Only 10 blocks cached, 990 read from disk
Very Bad (Temp Files):*
Buffers: temp read=5000 written=5000
= Query spilled to disk (work_mem too small)
Target:* Maximize "shared hit", minimize "shared read", zero "temp"
Enable explain in SQL editor first (dev only):
-- Run once in Dashboard SQL Editor
ALTER DATABASE postgres SET app.settings.explain TO 'on';
Then use in code:
const { data, error } = await supabase
.from('posts')
.select('*')
.eq('status', 'published')
.explain({ analyze: true, buffers: true })
EXPLAIN (ANALYZE, BUFFERS)ANALYZE after significant data changes