Builds a persistent hash index stored as a .vtri sidecar file alongside
the .vtr file. The index maps key hashes to row group indices, so an
equality predicate (filter(col == value)) names the row groups that may
hold a key without reading any column data.
Details
For composite indexes on multiple columns, pass a character vector.
Composite indexes accelerate AND-combined equality predicates
(e.g., filter(col1 == "a", col2 == "b")). The columns may be named in any
order.
A query opens the index for the column it filters on, so a store can carry
an index on each of several columns and a query pays only for the one it
uses. explain() reports the index a scan will probe. The index composes
with zone-map pruning and binary search on sorted columns.
The index holds one entry per distinct key per row group rather than one per row, so an index over a column with few distinct values stays small however many rows the store holds – which is what keeps a lookup off the size of the store.
Building one is bounded too: the entries are sorted through the streaming
memory budget (vectra_mem()) and written in a single pass, so an index over
a store larger than memory costs disk rather than RAM.
append_vtr() leaves the existing row groups where they are, so an index
stays valid across an append: it takes in the row groups just appended and
keeps the rest, reading only the new data rather than the whole store.
write_vtr() replaces a store, and removes the indexes of the store it
replaces.
An index records the store it was built on, by the store's row and row-group
counts and a fingerprint of its bytes. An index left behind by any other
change of the store – including a store replaced outside vectra by one of
the same shape, such as a download or a file renamed over the old path – is
reported as absent by has_index() and ignored by queries rather than
pruning row groups that may now hold matching rows. The same goes for one
that cannot be read at all: an index only ever saves a scan work, so an
unusable one costs speed and never rows. Indexes written by vectra 0.12.3
and earlier are superseded and read as absent; call create_index() again
to rebuild them.
A store written by vectra 0.12.3 or earlier carries no digest of its bytes,
so its fingerprint covers its layout (row-group sizes, block sizes and
column statistics) only. Such a store cannot be told apart from a
replacement whose blocks agree with it on all of those; rewriting it with
write_vtr() gives it a digest.