Late Materialization: GBase 8a’s Memory Offload Technique

Published on 2026-04-03

You only want to query a few columns, but the database pulls entire rows into memory, causing memory bloat, slow queries, and collapsing concurrency. GBase 8a's “late materialization” technology is designed to solve this problem. It uses row IDs in place of actual data for all intermediate computations, only decompressing, assembling, and loading the required columns at the final step. Real-world tests show memory usage can be reduced by tens to hundreds of times. In this article, we’ll deconstruct this “delayed unpacking” innovation.

Traditional Materialization: Why Memory Always Runs Out?

First, a concept: “materialization” means turning intermediate query results into tangible datasets.

Traditional databases (including standard columnar stores) use “early materialization”: during queries they first read and assemble entire rows into memory, then apply filtering and aggregation. For example, a table has 100 columns but you only query 5; the system loads all 100 columns into memory and then discards the 95 you don’t need — a huge waste.
In OLAP scenarios with large tables, this waste is magnified. With hundreds of millions of rows, each hundreds of bytes, memory can be exhausted before you even start calculating.

Late Materialization: Leaving Unpacking to the Last Step

GBase 8a’s late materialization follows simple logic: “Use row IDs for the entire computation; only load real data at the final step.”

The process has three steps:

01 Smart Scan Intelligent Filtering

Uses built-in intelligent indexes from columnar storage to quickly skip data blocks that don’t meet conditions. Index maintenance is automated — no user intervention needed.

02 Row ID Tagging Throughout Computation

All intermediate operations — filtering, JOINs, aggregation — only pass row IDs. A row ID uses just tens of bytes, while a full row may take hundreds or even thousands of bytes. This step minimizes memory footprint to the extreme.

03 Late Materialization to Generate Results

Only after all computations are complete and the final result set is determined does it decompress the needed columns, assemble them into complete rows, and return them to the user.

In a word: do the work first, pack later. Irrelevant data never touches memory.

Real-World Results: Tens to Hundreds of Times Memory Savings

Imagine a table with 100 million rows where you query 5 columns, and the final result set is 1 million rows.

Result: Memory usage drops from hundreds of MB or even GB to mere tens of MB. In tests, for large table aggregations and multi-table large JOINs, memory fell from dozens of GB to hundreds of MB — a reduction of tens to hundreds of times.

Beyond memory savings, CPU and I/O are also reduced: only needed columns are decompressed, only needed data is read, dramatically cutting wasteful operations.

How to Use It: Enabled by Default, Parameters Adjustable

1. Enabled Automatically by Default 

For columnar tables, GBase 8a enables late materialization by default with no manual configuration. Row-based tables, small tables, and temporary tables are automatically skipped.

2. Two Key Parameters

  • gbase_parallel_threshold** (parallel materialization threshold)  

When the result set row count exceeds this value, parallel materialization is enabled (fast but consumes memory); otherwise serial materialization is used (slower but memory-saving). Default: 10000.  

  • For memory-constrained, high-concurrency scenarios: increase to 50000 to favor serial materialization, saving memory.  

  • For abundant memory and speed: decrease to 1000 to favor parallel materialization, boosting efficiency.

  • gbase_result_threshold** (result set limit)

Prevents excessive result sets from causing memory overflow. The default is an extremely large value (128 TB), essentially unlimited.  

  • When memory is tight, set to 2 times the max rows of the largest table on a node, or a fixed row count (e.g., 200 million), to prevent a single query from exhausting memory.
     

Best Practices: Double the Benefits with Late Materialization + SQL Optimization

1. Proper Memory Heap Allocation

Intermediate computations in late materialization mainly use the “computation heap” (gbase_heap_large), so ensure sufficient memory. Recommended ratios (based on physical memory):

  • Data heap: 60%

  • Compute heap: 24%

  • Temporary heap: 8%

  • Total memory cap: 80%

2. Write Frugal SQL

  • Prohibit SELECT *: query only needed columns; otherwise assembling many columns will negate the benefits of late materialization.

  • Put filter conditions early: the stricter the WHERE clause, the better, screening out invalid data early.

  • Filter large tables before JOINing: reduce the scope of large tables before joining, preventing full data sets from entering the computation.

  • Avoid sorting large result sets: sorting loads the entire result set into memory. Try to sort after materialization or add a LIMIT.

3. Memory Protection in High-Concurrency Scenarios

  • Control concurrent sessions to avoid multiple queries collectively exhausting memory.

  • Set a per-session memory cap for operators.

  • Use monitoring commands to observe materialization memory usage in real time and adjust abnormal queries promptly.

Real-World Impact

  • Large table aggregation (1 billion+ rows): memory usage down by 70–90%, query speed improved by over 30%.

  • Multi-table large JOIN (3 tables with hundreds of millions of rows): intermediate result memory dropped from tens of GB to hundreds of MB, queries from minutes to seconds.

  • High-concurrency reporting: on the same hardware, concurrent queries increased 2–5x, average report latency reduced by 40%.

The core of late materialization is “materialize on demand, precision memory control” — completing intermediate computations at minimal cost and packing data only at the final moment. For massive-scale OLAP scenarios, this is one of GBase 8a’s key advantages over traditional databases.