September 8, 2023·5 min read·engineeringcassandraindexingstoragecompaction

Cassandra 5.0 alpha1 opens indexing and storage changes for evaluation

Cassandra 5.0 alpha1 includes Storage-Attached Indexing and new storage mechanisms. Vector search is absent, despite the presence of vector types and similarity functions.

Cassandra's first 5.0 alpha makes several changes to how the database locates and organises data available for evaluation. Its scope needs care. Mick Semb Wever's September 8 release announcement explicitly says that alpha1 excludes vector search, transactional cluster metadata, and Accord transactions. The release is an alpha preview of the 5.0 series. It does not establish that every capability associated with that series is ready to try.

That distinction leaves substantial work to examine. Storage-Attached Indexing changes secondary-index storage, while Unified Compaction Strategy makes compaction policy more flexible. The release also contains a new SSTable format. These changes concern the costs of maintaining and finding data, which remain relevant even when an application's query requirements have not changed.

I am drawn to Cassandra for systems that need active-active operation at scale. That is also why I regard it as a deliberate architectural choice. More flexible indexing is interesting in that context, but its execution model matters as much as its query syntax.

Secondary indexes remain local

The Storage-Attached Indexing README in the alpha1 tag describes a column-based local secondary index. SAI takes architectural ideas from SSTable-Attached Secondary Indexes, or SASI, but replaces the on-disk index formats. Strings use a byte-ordered trie. Numeric data uses a block-oriented balanced tree.

The storage layout also shares information between indexed columns. Related offsets and token information live once at the SSTable level. Several indexed columns therefore do not each need their own copy of that information. This gives the design a concrete reason to reduce index storage as more columns receive indexes.

The same README supplies a small example that can be run inside an existing test keyspace:

CREATE TABLE person (
    id int PRIMARY KEY,
    name text,
    age int
);

CREATE INDEX ON person (age) USING 'sai';

INSERT INTO person (id, name, age) VALUES (1, 'John', 21);
INSERT INTO person (id, name, age) VALUES (4, 'Caleb', 34);

SELECT * FROM person WHERE age >= 18 AND age <= 35;

Both inserted rows satisfy the predicate. The index makes a non-primary-key range query available through CQL. It does not imply age ordering. The implementation supports token ordering, and global queries use Cassandra range reads. Index updates happen synchronously with mutations without a read-before-write step.

Those details constrain the interpretation of the example. A compact query does not describe how much of the cluster participates. SAI's local organisation and its global execution mechanism answer different questions. I find the storage sharing particularly useful as a design choice, because it addresses the cost of indexing several columns without claiming to remove distributed query work.

Compaction policy becomes configurable by level

The Unified Compaction Strategy design shipped in the tag treats tiered and leveled compaction as related policies. Both organise data into exponentially growing levels. Their different merge thresholds produce different balances between read amplification and write amplification.

Leveled behaviour spends more rewriting work to reduce the number of overlapping sources a read encounters. Tiered behaviour favours writes and permits more read work. UCS represents that choice with a scaling parameter that can differ between levels. A table can therefore use tiered behaviour at its lowest level and more read-oriented behaviour higher up.

UCS also groups SSTables by density, calculated as size divided by the fraction of token space they cover. Splitting an output SSTable changes its size and token coverage together, so density can preserve its place in the compaction hierarchy. Non-overlapping shards permit concurrent compactions. This is the mechanism behind the design's combination of splitting and level management.

The design also connects output size to operational work. Large SSTables complicate streaming and repair, and long compactions retain resources while more files accumulate below them. Density-based splitting gives UCS a way to control file size while preserving its level structure.

Selecting an SSTable format is an explicit choice

The alpha1 NEWS file describes a trie-indexed SSTable format that removes the index summary component and does not require key caching. It also targets efficient searches inside partitions with very large row counts. These are changes to the primary storage format, separate from SAI's indexes on individual columns.

The distinction matters when evaluating the release. Adding an index to an application column and changing the format used to write SSTables are different operations. The SSTable API documentation makes the latter configurable. Format factories provide the components that read and write SSTables, and Cassandra discovers implementations through Java's service-loading mechanism.

The API separates formats available for reading existing files from the selected write format. Its default is big. The tagged cassandra.yaml likewise identifies big as the legacy default and documents bti as the trie-indexed alternative. The configuration shape for selecting it is:

sstable:
  selected_format: bti

This setting selects a write format. Its presence in the alpha does not mean that starting the new binary automatically converts every existing SSTable. The API documentation makes readers, writers, scrubbers, and verifiers responsibilities of the format implementation. That establishes a broader storage interface around the new format, beyond the lookup structure itself.

The alpha1 changelog includes CASSANDRA-18504 for a fixed-dimension vector type and CASSANDRA-18640 for vector similarity functions. Reading those entries without the release announcement could produce an incorrect account of this alpha. The announcement explicitly excludes vector search under CEP-30.

Representing a vector value and evaluating a similarity function are capabilities distinct from searching an indexed collection of vectors. The presence of the former does not demonstrate the latter. Alpha1 can be discussed accurately without suppressing the vector-related entries, provided that their scope remains explicit. Vector search is not in this alpha.

The changelog also records CEP-7 for Storage-Attached Indexes, CEP-25 for the trie-indexed SSTable format, and the implementation of Unified Compaction Strategy under CEP-26. These entries give the storage changes separate identities. Grouping them into a single search feature would obscure what each implementation changes.

I am more interested in those mechanisms than in treating the major version number as evidence of readiness. The runtime requirements reinforce that alpha evaluation involves concrete operating changes. The tagged NEWS file removes Java 8 support, sets Java 11 as the minimum, and labels Java 17 support experimental. Meanwhile, the release announcement requires Debian and Red Hat users to update package repository URLs. Even an isolated evaluation needs to account for the runtime and installation path of the actual alpha distribution.