postgres-performance
PostgreSQL query & performance tuning — reading EXPLAIN / EXPLAIN ANALYZE plans, choosing and designing indexes, fixing planner row-estimate errors with statistics, and diagnosing MVCC bloat / VACUUM. Use when a query is slow, when reading an EXPLAIN/EXPLAIN ANALYZE plan (seq vs index vs bitmap scan, nested-loop/hash/merge join, "Rows Removed by Filter", estimate-vs-actual skew), when choosing an index type or columns to index (btree/GIN/GiST/SP-GiST/BRIN/hash, multicolumn/partial/expression/covering), when ANALYZE/extended statistics give bad estimates, when tables bloat or autovacuum lags, or when tuning planner GUCs (random_page_cost, work_mem, effective_cache_size, enable_*). This is performance tuning — for the psql client see psql, for writing SQL/DDL see postgres-sql, for server config/replication & autovacuum GUC tuning see postgres-admin, for installing perf extensions (pg_stat_statements, auto_explain) see postgres-extensions. Newer features are tagged inline (pgNN+); PG18 is stable, PG19 is beta.
What this skill does
# PostgreSQL Performance — Query & Tuning ## Overview PostgreSQL's planner is **cost-based**: for each query it estimates the cost of many candidate plans (in arbitrary units where `1.0` ≈ one sequential page fetch) and runs the cheapest. Tuning is the craft of (a) **seeing** what plan it chose and why, then (b) pulling the **levers** that change its decision. There are four levers, and almost every fix is one of them: 1. **EXPLAIN** — the lens. Read the plan; compare the planner's **estimated** rows to the **actual** rows. Estimate errors are the root cause of most bad plans. 2. **Indexes** — give the planner a cheaper access path than scanning the whole table. 3. **Statistics** — `ANALYZE` and extended statistics fix the row estimates that drive plan choice. 4. **VACUUM / config** — keep dead tuples and bloat from inflating every scan; tune planner GUCs (`random_page_cost`, `work_mem`, `effective_cache_size`) so cost estimates match your hardware. **Mental model:** a slow query is a symptom. Don't reach for hints (Postgres has none) — find the *wrong estimate* or the *missing access path* and fix the cause. `EXPLAIN ANALYZE` tells you which. > **Disambiguation.** This skill is **query & performance tuning**. For the **`psql`** client > (`\timing`, `\x`, `\di`, running these commands) → **psql** skill. For **writing** the SQL/DDL > itself (SELECT, CTEs, window functions, join syntax) → **postgres-sql**. For **server config, > replication, and deep autovacuum GUC strategy** → **postgres-admin** (this skill covers VACUUM > *mechanics & why* and *planner* GUCs; server-wide sizing lives there). For **installing** the > profiling extensions named below → **postgres-extensions**. ### A note on version annotations Inline `(pgNN+)` marks the **minimum major version** that supports a feature, verified against the PostgreSQL docs/release notes. Anything unannotated is **bedrock** — present since the old 9.x line — and safe to assume everywhere. **PG18 is current stable; PG19 is beta** (tagged `(pg19+, beta)`). The full feature → version map with sources is in [references/version-features.md](references/version-features.md). Confirm your server with `SELECT version();` or `SHOW server_version;`. ## The slow-query loop ``` ① FIND the slow query pg_stat_statements (total/mean time) ─┐ → postgres-extensions ② SEE the plan EXPLAIN (ANALYZE, BUFFERS) <query> │ ③ READ it estimate vs actual? scan? join? sort spill? ④ FIX the cause index │ ANALYZE/stats │ rewrite │ VACUUM │ GUC ⑤ VERIFY re-run EXPLAIN ANALYZE; compare timing & rows ``` Always measure with `EXPLAIN (ANALYZE, BUFFERS)` on a realistic data volume — plans on a 100-row toy table do not predict plans on 100M rows (the planner switches strategies with size). ## EXPLAIN and EXPLAIN ANALYZE `EXPLAIN` shows the **estimated** plan (instant, no execution). `EXPLAIN ANALYZE` **runs the query** and adds **actual** timings and row counts so you can check the planner's guesses. ```sql EXPLAIN <query>; -- plan + cost estimates only EXPLAIN ANALYZE <query>; -- actually executes; adds actual time/rows (+ BUFFERS in pg18+) EXPLAIN (ANALYZE, BUFFERS) <query>; -- the workhorse: plan + reality + I/O EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, FORMAT JSON) <query>; ``` > ⚠️ `ANALYZE` **executes the statement** — for `INSERT/UPDATE/DELETE/MERGE` wrap it so it rolls back: > `BEGIN; EXPLAIN ANALYZE <dml>; ROLLBACK;` ### Options (PG19 synopsis) | Option | What it adds | Since | |--------|--------------|-------| | `ANALYZE` | Execute and show **actual** time, rows, loops | bedrock | | `BUFFERS` | Shared/local/temp blocks hit/read/dirtied/written (I/O) | option bedrock; **auto-on with `ANALYZE` (pg18+)** | | `VERBOSE` | Output columns, schema-qualified names, per-worker detail; +CPU/WAL/avg-read (pg18+) | bedrock | | `COSTS` | Estimated startup/total cost, rows, width (on by default) | bedrock | | `TIMING` | Per-node actual time (on with ANALYZE; turn **off** to cut clock overhead) | bedrock | | `SETTINGS` | Non-default planner GUCs in effect | `(pg12+)` | | `WAL` | WAL records/bytes/FPIs generated (needs ANALYZE) | `(pg13+)` | | `GENERIC_PLAN` | Plan a parameterized query with `$1` placeholders (no ANALYZE) | `(pg16+)` | | `SERIALIZE` | Cost of converting rows to text/binary for the client (`NONE`/`TEXT`/`BINARY`) | `(pg17+)` | | `MEMORY` | Planner memory consumption | `(pg17+)` | | `IO` | Asynchronous-I/O (AIO) stats per scan node (needs ANALYZE) | `(pg19+, beta)` | | `FORMAT` | `TEXT` (default) / `JSON` / `XML` / `YAML` — JSON/YAML are machine-parseable | bedrock | ### Anatomy of an `EXPLAIN ANALYZE` line ``` Index Scan using tenk2_unique2 on tenk2 t2 (cost=0.29..7.90 rows=1 width=244) (actual time=0.003..0.003 rows=1.00 loops=10) └── node type & target ├ startup..total cost ├ EST rows ├ width ├ first-row..all-rows ms ├ ACTUAL rows └ executions ``` - **cost=startup..total** — planner's estimate in cost units; a parent's cost includes its children. - **rows** (in cost parens) = **estimated** rows; **rows=N.NN** in the actual parens = **actual** rows, shown to 2 decimals **(pg18+)**. The single most important comparison in the whole plan. - **loops** — times the node ran. **actual time and actual rows are per-loop averages** → multiply by `loops` for totals (e.g. above: 0.003 ms × 10 = 0.03 ms total, 1 × 10 = 10 rows total). - **Buffers: shared hit=… read=…** — `hit` = found in cache; `read` = fetched from OS/disk. High `read` on a hot query is a caching/index problem. A worked, fully-annotated plan walkthrough is in [references/explain.md](references/explain.md). ## Reading a plan Read **inside-out / bottom-up**: leaf scan nodes produce rows; join/sort/aggregate nodes above combine them; the **top** line is the whole query's cost. Indentation = tree depth; `->` marks a child. ### Scan nodes (how a table/index is read) | Node | Means | Good / bad sign | |------|-------|-----------------| | **Seq Scan** | Read every page of the table | Fine for small tables or when most rows match; **bad** when a selective `WHERE` should have used an index | | **Index Scan** | Walk an index, then fetch each matching heap row | Good for **few** rows; random heap I/O makes it lose to Seq Scan for many rows | | **Index Only Scan** | Answer entirely from the index (no heap visit) | Best case — needs a covering index **and** an all-visible page (`Heap Fetches: 0` is the win) | | **Bitmap Heap Scan** + **Bitmap Index Scan** | Collect TIDs from index(es), sort by page, fetch in physical order | The middle ground for a medium row count; `BitmapAnd`/`BitmapOr` combine indexes | ### Join nodes | Node | Best when | Watch for | |------|-----------|-----------| | **Nested Loop** | One side tiny, inner has an index | Disaster if both sides are big and **actual** loops ≫ estimated (a row underestimate) | | **Hash Join** | Large, unsorted, equality join | Builds a hash of the smaller side; `Batches > 1` = spilled to disk → raise `work_mem` | | **Merge Join** | Both inputs already sorted on the key | Pays for a Sort if inputs aren't pre-sorted | ### Other common nodes `Sort` / **`Incremental Sort` (pg13+)** (uses a pre-sorted prefix; great with `LIMIT`) · `Hash`/ `HashAggregate`/`GroupAggregate` · `Partial Aggregate` + `Finalize Aggregate` (parallel two-stage) · `Gather` / **`Gather Merge` (pg10+)** (collect parallel-worker rows) · `Append`/`MergeAppend` (partitions/UNION) · `Materialize` · `Memoize` (pg14+, caches inner results) · `Limit`. ### The three signals that explain almost every slow query 1. **Estimate vs actual rows.** `rows=10` estimated but `rows=10000` actual → the planner picked the plan for the wrong size (nested loop that should've been a hash join, no index used, etc.). **Fix:** `ANALYZE`, raise statistics target, or add **extended statistics** for
Related in Backend & APIs
jfrog
IncludedInteract with the JFrog Platform via the JFrog CLI and REST/GraphQL APIs. Use this skill when the user wants to manage Artifactory repositories, upload or download artifacts, manage builds, configure permissions, manage users and groups, work with access tokens, configure JFrog CLI servers, search artifacts, manage properties, set up replication, manage JFrog Projects, run security audits or scans, look up CVE details, query exposures scan results from JFrog Advanced Security, manage release bundles and lifecycle operations, aggregate or export platform data, or perform any JFrog Platform administration task. Also use when the user mentions jf, jfrog, artifactory, xray, distribution, evidence, apptrust, onemodel, graphql, workers, mission control, curation, advanced security, exposures, or any JFrog product name.
cupynumeric-migration-readiness
IncludedPre-migration readiness assessor for porting NumPy to cuPyNumeric. Use BEFORE substantial porting work begins when the user asks whether code will scale on GPU, whether they should migrate to cuPyNumeric, which NumPy patterns transfer cleanly, what must be refactored before porting, or mentions pre-port assessment, scaling analysis, or refactor planning. Inspect the user's source code, look up NumPy usage, cross-reference the cuPyNumeric API support manifest, and distinguish distributed-scaling-friendly patterns from blockers such as unsupported APIs, scalar synchronization, host round-trips, Python/object-heavy control flow, shape/data-dependent branching, and in-place mutation hazards. Produce a verdict of READY, LIGHT REFACTOR, SIGNIFICANT REFACTOR, or NOT RECOMMENDED, with concrete refactor pointers.
alibabacloud-data-agent-skill
IncludedInvoke Alibaba Cloud Apsara Data Agent for Analytics via CLI to perform natural language-driven data analysis on enterprise databases. Data Agent for Analytics is an intelligent data analysis agent developed by Alibaba Cloud Database team for enterprise users. It automatically completes requirement analysis, data understanding, analysis insights, and report generation based on natural language descriptions. This tool supports: discovering data resources (instances/databases/tables) managed in DMS, initiating query or deep analysis sessions, real-time progress tracking, and retrieving analysis conclusions and generated reports. Use this Skill when users need to query databases, analyze data trends, generate data reports, ask questions in natural language, or mention "Data Agent", "data analysis", "database query", "SQL analysis", "data insights".
token-optimizer
IncludedReduce OpenClaw token usage and API costs through smart model routing, heartbeat optimization, budget tracking, and native 2026.2.15 features (session pruning, bootstrap size limits, cache TTL alignment). Use when token costs are high, API rate limits are being hit, or hosting multiple agents at scale. The 4 executable scripts (context_optimizer, model_router, heartbeat_optimizer, token_tracker) are local-only — no network requests, no subprocess calls, no system modifications. Reference files (PROVIDERS.md, config-patches.json) document optional multi-provider strategies that require external API keys and network access if you choose to use them. See SECURITY.md for full breakdown.
resend-cli
IncludedUse this skill when the task is specifically about operating Resend from an AI agent, terminal session, or CI job via the official resend CLI: installing/authenticating the CLI, sending/listing/updating/cancelling emails, batch sends, domains and DNS, webhooks and local listeners, inbound receiving, contacts, topics, segments, broadcasts, templates, API keys, profiles, or debugging Resend CLI/API failures. Trigger on mentions of Resend CLI, `resend`, `resend doctor`, `resend emails send`, `resend domains`, `resend webhooks listen`, `resend emails receiving`, or agent-friendly terminal automation.
alibabacloud-odps-maxframe-coding
IncludedUse this skill for MaxFrame SDK development and documentation navigation on Alibaba Cloud MaxCompute (ODPS). Helps answer MaxFrame API, concept, official example, and supported pandas API questions; create data processing programs; read/write MaxCompute tables; debug jobs (remote or local); and build custom DPE runtime images. Trigger when users mention MaxFrame, MaxCompute with MaxFrame, ODPS table processing, DPE runtime, MaxFrame docs/examples, DataFrame/Tensor operations, or GPU runtime setup. Works for both English and Chinese queries about Alibaba Cloud data processing with MaxFrame.