jed

EXPLAIN

EXPLAIN shows how jed will run a statement — which access path the planner chose (a full scan, a primary-key lookup, a secondary-index bound), how joins are shaped, and whether an ORDER BY is served by scan order or needs a sort. It renders the plan as an ordinary result set with three columns:

  • depth — the plan node’s nesting level (0 = the top of the pipeline). The rows are a pre-order walk of the plan tree, so they read top-down as execution reads bottom-up.
  • node — the operator (Scan, Filter, Sort, Aggregate, Nested Loop, Limit, …).
  • detail — its attributes (the access path, key counts, and so on; - when it has none).

The plan is a deterministic function of the query and the database, so every jed core renders the identical plan.

A full scan

With no usable bound, a scan reads the whole table. touched= reports how many columns the query actually references.

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

A primary-key lookup

A WHERE on the primary key bounds the scan to a point lookup — the PK bound detail names the column and predicate. The original WHERE stays as the residual Filter above the scan.

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

A secondary-index bound

A predicate on an indexed non-key column uses the index — Index bound: using <index>. An equality (region = 1) seeks the matching entries:

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

A range on an indexed column (region > 1, <, <=, >=, BETWEEN) is bounded the same way — jed range-scans the index leaves instead of the whole table:

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

On a composite index over (a, b, …) the bound extends to a multi-column prefix: an equality on the leading columns, optionally followed by a range on the next (a = 1 AND b > 3). The WHERE always stays the residual filter, so the rows are identical to a full scan — only the work drops.

An OR / IN-list of keys

An IN-list on the primary key — or the equivalent id = 1 OR id = 3 OR id = 5 — is a union of point lookups, not a full scan: the PK point set detail lists the keys, and jed seeks each one (de-duplicated) instead of walking the whole table. The same applies to an indexed non-key column (Index point set: using <index>).

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

An index-nested-loop join

When a join’s inner relation is matched on its own primary key against a column of the outer relation (c.id = t.city_id), jed seeks that inner row per outer row instead of re-scanning the whole inner table — an Index-nested-loop PK bound on the inner Scan. The join turns O(N·M) into O(N·log M), and the plan stays a Nested Loop whose inner child names the per-outer-row bound.

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

Aggregation

GROUP BY adds an Aggregate node over the scan, carrying the grouping-key and aggregate counts.

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

EXPLAIN ANALYZE — the real cost

Plain EXPLAIN only plans the statement — it never runs it, so EXPLAIN DELETE … deletes nothing. EXPLAIN ANALYZE also executes the statement and reports its actual accrued cost and row count on an Analyze node. Because jed’s cost is deterministic, this figure is exact and reproducible — not a wall-clock estimate.

Ctrl/⌘ + Enter to run · in-memory

No results yet. Run a query to see output.

EXPLAIN ANALYZE of an INSERT / UPDATE / DELETE does run the mutation (and commits it), exactly like PostgreSQL. Use plain EXPLAIN to inspect a write’s plan without changing any data.

jed — an embeddable, strictly-typed SQL database.