Skip to content

AxonOps — AI-Native Control Plane for Open Source Data Platforms

Index Query Execution

Index queries in Cassandra employ distinct execution strategies compared to primary key queries. The distributed coordination model varies significantly between index implementations: legacy Secondary Index (2i) and SASI use a scatter-gather pattern, while Storage Attached Index (SAI) uses adaptive range reading.


Queries containing the complete partition key identify replicas deterministically via token computation:

Primary Key Query: Deterministic Replica SelectionPrimary Key Query: Deterministic Replica SelectionReplica set for token(partition_key)Determined via consistent hashingNode A(replica)Node D(replica)Node F(replica)ClientCoordinator(any node)Remaining nodes(excluded from query)1. query4. result2. read request3. response2. read request3. response

Queries lacking a partition key constraint cannot use token-based routing. Each node indexes only the partitions it owns, so distributed coordination across nodes is required to satisfy an index query. The design of that coordination — and its performance characteristics — differs substantially between Cassandra's three index implementations.


Secondary Index is Cassandra's original indexing mechanism, available since the earliest versions. Each indexed column is backed by a hidden table, replicated independently from the base table. The coordinator broadcasts the query to one replica per token range (scatter-gather) and aggregates all partial results before returning to the client.

Because index data lives in a separate table, compaction cycles are independent of the base table, which can cause temporary divergence between index entries and base table rows. The scatter-gather model means query latency is always bounded by the slowest node in the cluster and scales poorly as the cluster grows.

See Secondary Index (2i) for execution detail.

SASI, introduced in Cassandra 3.4 (CASSANDRA-6661), attaches index structures directly to SSTables. The index is created, compacted, and removed in lockstep with the base data, eliminating the divergence problem of 2i. Multi-predicate queries benefit from single-pass intersection within each SSTable rather than separate lookups joined at the coordinator.

The distributed coordination model is unchanged from 2i: SASI still uses scatter-gather across all token ranges. A global SASI query contacts every node in the cluster, and latency remains bounded by the slowest respondent.

See SASI for execution detail.

SAI, introduced in Cassandra 5.0 (CEP-7, CASSANDRA-16052), replaces the scatter-gather model with adaptive range reading. The coordinator estimates a concurrency factor from local data statistics and the query LIMIT, dispatches requests to a bounded subset of token ranges, and iterates in additional rounds only if the limit is not yet satisfied. Queries that can be answered from an early subset of ranges never contact the full cluster.

SAI also propagates index status via gossip, allowing the coordinator to route around nodes whose index is not queryable. Multi-predicate queries are handled by the Token Flow framework, which merges index streams using Boolean logic rather than performing separate scans.

See SAI for execution detail.


Queries without a partition key constraint require coordination across all token ranges:

-- Global: all token ranges involved
SELECT * FROM users WHERE city = 'NYC';
SELECT * FROM events WHERE level = 'ERROR' LIMIT 1000;
Index TypeExecution Model
2i / SASIScatter to all nodes, gather all results
SAIAdaptive range reading with concurrency factor

Including the partition key in a secondary index query limits node contact to the replica set for that partition:

-- Partition-restricted: RF nodes only
SELECT * FROM users WHERE user_id = ? AND city = 'NYC';
SELECT * FROM events WHERE device_id = ? AND level = 'ERROR';
Partition-Restricted Query: Bounded Node ContactPartition-Restricted Query: Bounded Node ContactPartition replicas only (RF nodes)Excluded from queryNode A(replica)Node D(replica)Node F(replica)Node BNode CNode EClientCoordinator1. query withpartition key4. result2. read3. filtered result
Query TypeNodes ContactedLatency CharacteristicsCluster Scalability
Global (2i/SASI)All token rangesBounded by slowest nodeDegrades linearly
Global (SAI)Adaptive subsetBounded by concurrency factorImproved via adaptation
Partition-restrictedRF nodesPredictable, boundedConstant

Factor2i / SASISAI
Coordinator loadHigh (all results buffered)Reduced (streaming, bounded)
Network utilizationProportional to cluster sizeAdaptive to result density
Memory pressureUnbounded result accumulationBounded via concurrency factor
Index build visibilityLimitedGossip-based status propagation
Failed index handlingManual detection requiredAutomatic coordinator filtering

PatternRationale
Include partition key when possibleRestricts query to RF nodes
Apply LIMIT clauseEnables SAI early termination; reduces scatter-gather result set
Prefer high-selectivity predicatesReduces post-filtering overhead
Combine multiple SAI-indexed predicatesLeverages Token Flow intersection

Optimal: partition-restricted with index

SELECT * FROM orders
WHERE customer_id = ? -- partition key constraint
AND status = 'pending'; -- SAI index predicate

Acceptable: global query with limit

SELECT * FROM orders
WHERE status = 'pending' -- SAI index predicate
AND created_at > ? -- SAI range predicate
LIMIT 100; -- enables early termination

Suboptimal: unbounded global query

SELECT * FROM orders
WHERE status = 'pending'; -- unbounded result set, all nodes contacted

# SAI-specific metrics
org.apache.cassandra.metrics:type=StorageAttachedIndex,name=*
# Per-table read latency
org.apache.cassandra.metrics:type=Table,keyspace=*,scope=*,name=ReadLatency
# Coordinator request metrics
org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency
SymptomProbable CauseRemediation
Elevated P99 latencyTail latency in scatter-gatherMigrate to SAI, add partition key
Query timeoutsUnbounded result setsApply LIMIT clause
Coordinator GC pressureResult set accumulationPagination, query redesign
Index query failuresNon-queryable index stateCheck gossip status, rebuild index

  • Secondary Index (2i) - Scatter-gather execution, hidden table storage
  • SASI - Scatter-gather execution, SSTable-attached storage
  • SAI - Adaptive range reading, Token Flow framework
  • Index Overview - Index type selection criteria
  • Consistency - Consistency level impact on index queries
  • Partitioning - Token distribution and routing