Overview
ClickHouse 25.9 introduces streaming secondary indices, a fundamental change to how secondary indexes (minmax, set, bloom filter, vector, text) are evaluated during query execution. Instead of fully scanning indexes upfront before reading table data, the new approach interleaves index checks with data reads incrementally and on-demand, eliminating startup delays and reducing both query latency and memory usage, especially for LIMIT queries on large tables.
What You'll Learn
How ClickHouse streaming secondary indices eliminate upfront index scanning by interleaving index checks with data reads
Why sequential index evaluation causes startup delays and wastes work for LIMIT queries on large tables
How to enable or disable streaming secondary indices using the use_skip_indexes_on_data_read setting
When streaming secondary indices provide the greatest performance benefit (early-exit queries on large tables)
Prerequisites & Requirements
- Understanding of ClickHouse granules as the smallest processing units (typically 8,192 rows each)
- Familiarity with secondary index types in ClickHouse (minmax, set, bloom filter, vector, text)
- Basic understanding of ClickHouse primary index analysis and MergeTree engine
- ClickHouse 25.9 or later for streaming secondary indices support
Key Questions Answered
What are streaming secondary indices in ClickHouse 25.9?
How did ClickHouse evaluate secondary indices before version 25.9?
How to enable streaming secondary indices in ClickHouse?
How much faster are streaming secondary indices compared to sequential index scans?
Why are LIMIT queries inefficient with traditional ClickHouse secondary index evaluation?
What types of secondary indices benefit from streaming evaluation in ClickHouse?
What are the drawbacks of upfront secondary index evaluation in ClickHouse?
Key Statistics & Figures
Technologies & Tools
Some links below are affiliate links. We may earn a commission if you make a purchase.
Key Actionable Insights
1Enable streaming secondary indices for LIMIT queries on large tables by setting use_skip_indexes_on_data_read = 1. This eliminates the need to fully scan secondary indices upfront, allowing ClickHouse to stop immediately once the LIMIT condition is satisfied, dramatically reducing both query time and memory usage.This is most impactful for queries with highly selective WHERE filters over huge tables, particularly when the secondary index itself is large (the demo showed a 2.21 GiB bloom filter index on a billion-row table).
2Audit your existing LIMIT queries on large tables with secondary indices for potential performance improvements. Queries that previously suffered from long startup delays due to upfront index scanning will see the most dramatic speedups when streaming indices are enabled, as demonstrated by the 4x improvement in the article's benchmark.The improvement comes from two mechanisms: concurrent index scanning and data processing, plus early termination when LIMIT conditions are met.
3Consider the size of your secondary indices relative to your data when evaluating the impact of streaming indices. In scenarios where secondary indices alone exceed terabytes (as mentioned in ClickHouse's internal test runs with trillions of log records and 6 TB+ compressed indices), the startup delay from upfront scanning can be severe.Even at smaller scales, the benefit is measurable — the demo showed a 2.21 GiB bloom filter index causing a ~10 second delay that was reduced to ~2.4 seconds with streaming.
4When benchmarking streaming secondary indices, isolate the effect by setting max_threads = 1 and disabling the query condition cache (use_query_condition_cache = 0). Clear the OS page cache between runs to ensure fair comparisons. In production, multi-threaded execution will provide additional benefits beyond what single-threaded benchmarks show.The article notes that while the demo uses single-threaded execution for clarity, in reality multiple threads process many granules concurrently, so production improvements may vary.
5Use bloom_filter indices with fine granularity (granularity 1) for point lookups on string columns in large tables. Combined with streaming secondary indices, this allows ClickHouse to efficiently skip non-matching granules incrementally without paying the cost of scanning the entire index upfront.The article's demo used bloom_filter(0.0001) with granularity 1 and index_granularity = 1024, creating a 2.21 GiB index on a billion-row table that performed well with streaming evaluation.