An index that carries enough columns to satisfy the whole query

InnoDB covering indexes carry the query's columns

A covering index contains the columns needed to evaluate a particular query and return its requested values. In InnoDB, secondary-index records also carry the primary-key columns, so a query can be covered without explicitly listing the primary key again in the secondary-index definition. Coverage is a relationship between one query and an index, not a permanent property that applies to every query against the table. ...

March 3, 2028 · 4 min · XB Field Notes
An index that ignores the rows you never ask for

Partial indexes trim a column

Not every row deserves an index slot; a partial index keeps the tree thin exactly where the query never looks. Most tables have a skew the schema pretends not to see: ninety percent of orders are closed, nearly all events are processed, the flag column is false almost everywhere. A full index dutifully records all of it, charging maintenance on every write to protect lookups that only ever touch the small live slice. The partial index stops paying for the rows nobody queries. ...

February 15, 2028 · 4 min · XB Field Notes
An index built only for exact-match key lookups.

Hash indexes recheck collisions and maintain changed keys

PostgreSQL hash indexes narrow an equality search using a hash code, then verify the original value in the table. A hash match is a candidate, not proof of equality. Two different values can have the same code, and different codes can also map to the same bucket. Neither collisions nor shared buckets imply incorrect query results when the normal recheck is performed. ...

January 24, 2028 · 5 min · XB Field Notes
A document column indexed with GIN for path lookups.

Postgres JSONB pairs with GIN for flexible queries

A PostgreSQL JSONB column can hold documents with different shapes, but efficient querying still requires a precise contract between the predicate and the index. A GIN index on the whole document supports particular JSONB operators. It does not automatically accelerate every expression that extracts a field from that document. ...

July 28, 2027 · 5 min · XB Field Notes
A balanced tree that speeds equal and range lookups.

A Postgres index lives to answer a query

An index is valuable because it changes the work needed by a real query. Counting indexed columns is not a useful success measure. A narrow B-tree that finds one customer’s newest three orders can outperform a wider structure that cannot supply the needed ordering, while a query reading almost every row may correctly ignore both. Evaluate access, ordering, and result volume together. ...

July 20, 2027 · 4 min · XB Field Notes
An index built on the output of a function, enabling searches on its value.

A function index precomputes a value at write time

An expression index stores the result of a computation as an index key. A query comparing lower(email) can search those precomputed keys instead of evaluating lower over every table row. This moves work into index creation and maintenance. It does not change the stored email, guarantee that every query uses the index, or make every textual variation a different expression. ...

May 5, 2027 · 4 min · XB Field Notes
A WHERE-constrained index that occupies less space and serves a narrow predicate.

A partial index stores only the rows that matter

A partial index can keep a frequently queried subset of rows in a smaller structure. An index on job id WHERE status is open is a useful candidate when open jobs are rare and most requests target them. Its availability depends on what the planner can prove about each query, not merely on whether the application happens to pass “open” during one execution. ...

April 27, 2027 · 4 min · XB Field Notes
Two index flavors: range-capable btree and equality-only hash.

Choose B-tree or hash from the required operations

PostgreSQL’s default B-tree index supports several common query requirements: equality, ranges, ordered access, and uniqueness enforcement. A hash index supports a narrower equality access path. Choosing between them starts with the required operators and constraints, then proceeds to measurement. Saying that hashes are always faster for equality, or that PostgreSQL almost never chooses them, replaces a workload question with an unsupported generalization. ...

February 7, 2027 · 5 min · XB Field Notes