Indexes and pruning
Table and attribute indexes, committed-tail coverage, per-part regions, and the exact limits of each index type.
Indexes are declared with the schema and maintained by the engine. The current
SQL surface does not provide a standalone CREATE INDEX statement.
Table index syntax
CREATE TABLE events (
id UInt64,
tenant UInt64,
amount Decimal(18, 2),
tag String,
INDEX ix_tenant tenant TYPE bitmap GRANULARITY 1,
INDEX ix_amount amount TYPE minmax GRANULARITY 1,
INDEX ix_tag tag TYPE bloom_filter GRANULARITY 4,
PRIMARY KEY (id)
) SETTINGS storage_policy = 'disk_data';Grammar:
INDEX name column TYPE kind[(parameters)] [GRANULARITY n]
[SETTINGS storage_policy = 'policy']GRANULARITY must be positive. set(N) requires its size parameter. An
index-specific storage policy can override the table's inherited index policy.
Current index types
| Type | Current use |
|---|---|
bitmap | Exact value-to-position postings; equality, IN, supported negation, and bitmap AND/OR can produce exact candidate rows. |
minmax | Proves a part or range cannot contain a matching value. |
bloom_filter | Probabilistic presence check; false positives scan, false negatives are not allowed. |
set(N) | Bounded distinct-value region used to prove absence. |
hnsw | Approximate nearest-neighbor index for supported vector(N) columns. |
bitmap can prune granules and provide row candidates. minmax,
bloom_filter, and set are proof-empty indexes: they skip a part when
absence is provable, but do not return matching row positions.
Tail and part coverage
Disk-backed reads consult both:
- index metadata stored with immutable parts and rebuilt on compaction; and
- committed-tail metadata for unflushed rows.
This prevents a selective query from becoming a full tail scan solely because
recent rows have not flushed. EXPLAIN distinguishes table/part proof-empty
pruning from bitmap granule pruning, and query profiles expose the number of
shards and granules considered and pruned.
Attribute indexes
Attribute definitions use a shorter suffix:
CREATE TABLE account_state (
account_id UInt64,
ATTRIBUTE (
tier String INDEX bitmap,
balance Decimal(20, 2) VALUE INDEX minmax
)
) SETTINGS
kind = 'attribute',
storage_policy = 'memory_data',
entity = (account_id);INDEX applies to attribute/projection access. VALUE INDEX applies to the
underlying value stream used for temporal reconstruction.
Operational guidance
- Index the predicates that eliminate meaningful work; every index adds build, memory, and compaction cost.
- Use
system.column_statsto inspect approximate distinct counts for indexed columns. - Use
system.queriesorsystem.query_logto confirm pruning instead of assuming an index was selected. - A result never depends on an index being present. Unsupported or unselective paths fall back to an exact scan.
Per-part regions, committed-tail indexing, and local rebuild-on-compaction are implemented in the single-node profile. Topology placement for indexes remains part of the Experimental storage-policy surface.