pub enum IndexKind {
BTree(PersistentBTreeMap<IndexKey, Vec<RowLocator>>),
Nsw(NswGraph),
Brin {
column_type: DataType,
},
Gin(PersistentBTreeMap<String, Vec<RowLocator>>),
GinTrgm(PersistentBTreeMap<String, Vec<RowLocator>>),
GinFulltext(PersistentBTreeMap<String, Vec<RowLocator>>),
GinJsonb(PersistentBTreeMap<String, Vec<RowLocator>>),
}Variants§
BTree(PersistentBTreeMap<IndexKey, Vec<RowLocator>>)
v4.40: structural-sharing B-tree over IndexKey. Replaces the v0.8
BTreeMap<IndexKey, Vec<usize>> — Index::clone is now an Arc
bump regardless of index size, so Catalog::clone inside the
v4.34 auto-commit wrap stays O(1) even for tables with secondary
indices (the case that bottlenecked v4.39 at 1M rows in the
sweep).
v5.1: value type widened from Vec<usize> to Vec<RowLocator> so
a single key can point to a mix of hot-tier rows (RowLocator::Hot,
equivalent to the pre-v5 usize row index) and cold-tier rows
(RowLocator::Cold { segment_id, page_offset }) once the v5.2
freezer starts producing them. Pre-v5.2 only Hot entries appear
— the on-disk encoding stays at FILE_VERSION 8 (raw u64 row index)
because every locator round-trips through RowLocator::from_legacy_v8_u64
without information loss. FILE_VERSION 9 with tagged encoding lands
alongside the first freezer commit (v5.1 step 2b / v5.2).
Nsw(NswGraph)
Navigable-small-world graph for vector kNN search.
Brin
v6.7.1 — BRIN (Block Range INdex). Pure metadata: BRIN
indexes carry NO in-memory key→locator map. The (min,
max) summaries live in each cold-tier segment’s v2
envelope sidecar; the BRIN entry in Table.indices only
records THAT a BRIN index exists on this column so the
segment encoder + planner can opt into the summary path.
Fields
Gin(PersistentBTreeMap<String, Vec<RowLocator>>)
v7.12.3 — GIN inverted index over a tsvector column.
Storage shape: lexeme word → Vec<RowLocator>. The posting
list per word is appended in row-order, so range scans are
O(matching rows) once the per-word lookup is done. Multi-
term queries intersect / union posting lists.
IndexKey::from_value(TsVector) returns None — GIN doesn’t
participate in try_index_seek (which is BTree-equality-keyed).
The engine consults this index through try_gin_lookup on
WHERE col @@ tsquery predicates instead.
Backed by a PersistentBTreeMap so Catalog::clone (the
per-write snapshot) stays O(1) — same structural-sharing
invariant as BTree.
GinTrgm(PersistentBTreeMap<String, Vec<RowLocator>>)
v7.15.0 — USING gin (col gin_trgm_ops) over a TEXT
column. Posting lists map trigram (PG-compatible 3-byte
shingle on the lower-cased + space-padded input) to row
locators. The planner uses this index to accelerate
WHERE col LIKE '…' / ILIKE '…' / similarity(col, q) > t — every literal run of length ≥ 1 in the pattern
produces a trigram set, the engine intersects the posting
lists, and the LIKE / similarity predicate is re-evaluated
per candidate row to filter the over-approximation.
Persisted via tag-4 index payload in FILE_VERSION 24+.
GinFulltext(PersistentBTreeMap<String, Vec<RowLocator>>)
v7.17.0 Phase 2.2 — MySQL FULLTEXT KEY (col) over a
TEXT / VARCHAR column. Posting lists map
tsvector('simple') lexeme to row locators. At insert /
build time the engine derives the lexemes from the cell
via the same lower-case tokenisation rule as
to_tsvector('simple', ...) — the column itself stays a
plain text type on disk (mysqldump round-trips would be
broken otherwise). The planner uses this index to
accelerate MySQL-shape MATCH(col) AGAINST('term')
queries by mapping them onto the existing tsquery @@
walker. Persisted via tag-5 index payload in
FILE_VERSION 33+.
GinJsonb(PersistentBTreeMap<String, Vec<RowLocator>>)
v7.37.8(sentori Epic 5 P2)— USING gin (col) over a
JSON / JSONB column. Posting lists map a canonical
(path, leaf) token(see crate::jsonb_gin::extract_tokens)
to row locators so the planner can resolve
<col> @> <jsonb_literal> to a candidate row set via
posting-list intersection + per-row json::contains
re-verification. Pre-7.37.8 the same DDL loaded as a
BTree fallback so pg_dump JSONB-GIN scripts kept loading
without query-time acceleration. Persisted via tag-6 index
payload in FILE_VERSION 51+.
Implementations§
Source§impl IndexKind
impl IndexKind
Sourcepub fn approx_resident_bytes(&self) -> u64
pub fn approx_resident_bytes(&self) -> u64
v7.31 (memory campaign, C2) — bytes this index variant holds
resident in RAM, computed by walking its OWN structure rather
than a parametric guess made by the engine. Replaces the old
spg_admin::memory_stats inline match, which charged NSW with
a stale m_max_0 * 8 per node (neighbour slots are u32 = 4 B
since v6.1.x, and most nodes never fill m_max_0) and lumped
every GIN family index into a flat 1 KiB token — a gross
undercount for the text-heavy posting lists that dominate
mailrs’ footprint. Per-entry container overhead uses the
3-word (24 B on 64-bit) Vec/String header as the charge.
O(index entries): operator/monitoring surface (memory_stats /
spg_memory_stats), not a query path.