Overview
Over the years, ClickHouse has introduced a series of layered optimizations to aggressively reduce I/O. These techniques form the foundation of its speed and efficiency:
While the aforementioned I/O optimizations can significantly reduce data read, they still assume that all columns for rows passing the
WHERE clause must be loaded before running operations like sorting, aggregation, or LIMIT. But what if some columns aren’t needed until later, or some data, despite passing the WHERE clause, is never needed at all?
That’s where lazy materialization comes in. It is an orthogonal enhancement that completes the I/O optimization stack:
- Indexing, together with
PREWHERE, ensures that only rows matching column filters in theWHEREclause are processed. - Lazy materialization builds on this by deferring column reads until they’re actually required by the query execution plan.
Even after filtering, only the columns needed for the next operation - such as sorting - are loaded immediately.
Others are postponed and, due to
LIMIT, are often read only partially, just enough to produce the final result. This makes lazy materialization especially powerful for Top N queries, where the final result may only require a handful of rows from certain, often large, columns.
A worked example
We highly recommend the blogpost “ClickHouse gets lazier (and faster): Introducing lazy materialization” for a deep dive on lazy materialization. The example below is taken from the aforementioned blogpost and reproduced here to demonstrate how a ClickHouse query can go from 219 seconds to just 139 milliseconds (a 1576× speedup) with lazy materialization. To benefit from indexing andPREWHERE, a query needs filters, on primary key columns for indexing, and on any columns for PREWHERE.
Lazy materialization layers cleanly on top, but unlike the other optimizations mentioned previously, it can also speed up queries with no column filters at all.
Consider the following example query which finds Amazon reviews with the highest number of helpful votes, regardless of date, product, rating, or verification status, and returns the top 3 along with their title, headline, and full text.
First running the query (with cold filesystem caches) with lazy materialization disabled (using query_plan_optimize_lazy_materialization):
Query
Response
Query
Response
How to confirm lazy materialization in the query execution plan
You can observe usage of lazy materialization for the previous query by inspecting the query’s logical execution plan using theEXPLAIN clause: