Larger-than-memory processing
Larger-than-memory processing is a query engine's ability to correctly and efficiently process datasets or intermediate results that exceed the amount of RAM available, typically by spilling data to disk.
Overview
Many query operations — joins, sorts, grouped aggregations, window functions — need to materialize intermediate state that can be much larger than the input data, and larger still than the memory available on the machine running the query. An engine without larger-than-memory support simply fails with an out-of-memory error once that state doesn't fit; an out-of-core engine instead spills the excess to disk and continues, at the cost of extra I/O.
Why It's Hard
The difficulty isn't just "write some data to disk" — it's doing so without a catastrophic performance cliff, and without needing to know ahead of time how much memory a query will require. Good out-of-core designs, like radix partitioning for hash-based operators, degrade gradually as more data spills, rather than collapsing in performance the moment memory runs out.
DuckDB's Larger-Than-Memory Support
DuckDB has out-of-core support for the operators most likely to blow up memory: grouping, joining, sorting, and windowing. When a hash table built for a GROUP BY or a join doesn't fit in memory, DuckDB partitions and spills data to a temporary directory on disk rather than throwing an out-of-memory error, using radix partitioning to keep the performance degradation gradual instead of a sudden cliff. This works both for on-disk databases and for DuckDB running fully in-memory, since spilling always writes to a temp directory on disk regardless of where the source database lives.
There are limits: a handful of aggregate functions, like list() and string_agg(), don't support spilling and must hold their full state in memory, and queries with multiple simultaneous blocking operators can still exhaust memory in some cases. You can configure spilling behavior with SET memory_limit and SET temp_directory.
Copy code
SET memory_limit = '4GB';
SET temp_directory = '/fast/local/disk/tmp';
Related terms
An in-memory database is a type of database management system that primarily relies on a computer's main memory (RAM) for data storage and processing, as…
Temporary table →A temporary table is a table scoped to a single session (or transaction) that is automatically dropped when the session ends, used for intermediate results that don't need to persist.
query engine →A query engine parses, optimizes, and executes SQL queries against data sources. Learn its core architecture, how it differs from a database, and see examples like DuckDB and Presto.
HyperLogLog →HyperLogLog is a probabilistic algorithm for estimating the number of distinct elements in a large dataset (cardinality) using a small, fixed amount of memory, at the cost of a small, predictable error margin.
Dask →Dask is a Python library for parallel and distributed computing that scales pandas-like DataFrame, NumPy-like array, and general task-graph workloads across multiple cores or a cluster.
Massively Parallel Processing (MPP) →Massively Parallel Processing (MPP) is a database architecture in which many independent nodes, each with their own CPU, memory, and storage, cooperate to execute a single query in parallel across a cluster.
FAQS
DuckDB partitions the data using radix partitioning and spills the excess to a temporary directory on disk, continuing the query rather than failing with an out-of-memory error.
Yes. Some aggregate functions, such as list() and string_agg(), require holding their full state in memory and don't support offloading to disk, and queries combining multiple blocking operators can still run out of memory in some cases.
