This is an automated email from the ASF dual-hosted git repository.
vinothchandar pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/hudi.git
The following commit(s) were added to refs/heads/asf-site by this push:
new 0a1edf9e5548 docs(blog): streaming, write-heavy, read-heavy and
benchmark comparisons (#19273)
0a1edf9e5548 is described below
commit 0a1edf9e5548ae0191b162c22f5fbbb5aadb0673
Author: vinoth chandar <[email protected]>
AuthorDate: Tue Aug 11 15:45:07 2026 -0700
docs(blog): streaming, write-heavy, read-heavy and benchmark comparisons
(#19273)
---
...8-11-hudi-vs-iceberg-for-streaming-ingestion.md | 100 ++++++++++++++
...hudi-vs-delta-lake-for-write-heavy-workloads.md | 120 +++++++++++++++++
...08-13-hudi-vs-iceberg-performance-benchmarks.md | 109 +++++++++++++++
...d-heavy-workloads-point-lookups-with-indexes.md | 146 +++++++++++++++++++++
website/static/llms.txt | 4 +
5 files changed, 479 insertions(+)
diff --git a/website/blog/2026-08-11-hudi-vs-iceberg-for-streaming-ingestion.md
b/website/blog/2026-08-11-hudi-vs-iceberg-for-streaming-ingestion.md
new file mode 100644
index 000000000000..91ed12118dec
--- /dev/null
+++ b/website/blog/2026-08-11-hudi-vs-iceberg-for-streaming-ingestion.md
@@ -0,0 +1,100 @@
+---
+title: "Apache Hudi vs Apache Iceberg for Streaming Ingestion"
+excerpt: "Both formats accept streaming writes, but their architectures
diverge sharply under continuous ingestion. A mechanism-level comparison of
write paths, commit cadence, compaction, and concurrency."
+description: "Hudi vs Iceberg for streaming ingestion: write paths, commit
cadence, small files, compaction, and multi-writer concurrency compared at the
mechanism level."
+authors: [sivabalan]
+category: deep-dive
+image:
/assets/images/blog/2025-07-02-Lakehouse-Architecture-apache-hudi-and-apache-iceberg.png
+tags:
+- comparison
+- apache iceberg
+- streaming
+- data lakehouse
+---
+
+Both Apache Hudi and Apache Iceberg can ingest streaming data, but they are
built around different assumptions about how often a table is written to.
Hudi's architecture is streaming-native: Merge-on-Read tables absorb updates as
lightweight log appends, commits land every few minutes with automatic file
sizing, compaction and clustering run asynchronously without ever blocking
ingestion, and non-blocking concurrency control lets multiple writers land data
into the same file groups. Iceb [...]
+
+<!--truncate-->
+
+That is the short answer to "Hudi vs Iceberg for streaming." The rest of this
post walks through the mechanisms behind it: what continuous ingestion actually
stresses in a table format, how each format's write path behaves under it, what
minute-level commits do to each format's metadata, and how each keeps readers
fast while the writers never stop. The goal is a fair, mechanism-level
comparison — both are excellent open table formats, and the differences that
matter here are architectura [...]
+
+## What Continuous Ingestion Stresses in a Table Format
+
+Batch and streaming workloads stress a table format in very different places.
A nightly batch job commits once, writes well-sized files, and leaves a long
quiet window for maintenance. A streaming pipeline inverts every one of those
properties:
+
+- **Commit frequency.** A pipeline targeting minute-level freshness commits
hundreds of times a day, every day. Every structure the format touches per
commit — metadata files, manifests, timeline entries — gets exercised at that
rate.
+- **Small files.** Each micro-commit writes only a sliver of data. Without
countermeasures, a week of minute-level commits leaves behind tens of thousands
of files, and query planning and scan performance degrade with file count.
+- **Write amplification on updates.** Streams from CDC sources are
update-heavy. If applying an update means rewriting the columnar file that
contains the old value, a trickle of changes turns into a torrent of rewritten
bytes.
+- **Concurrent maintenance.** There is no quiet window. Compaction,
clustering, and cleaning must run *while* ingestion continues, without blocking
it and without being starved by it.
+- **Exactly-once delivery.** The format's commit protocol has to compose with
Flink checkpoints or Spark Structured Streaming epochs so that failures and
retries never duplicate or drop records.
+
+These pressures are exactly what a [streaming data
lake](/blog/2026/07/21/what-is-a-streaming-data-lake) has to absorb, and they
are where the two formats' designs part ways.
+
+## The Write Path Compared
+
+**Hudi.** Hudi's [Merge-on-Read table type](/docs/table_types) organizes data
into file groups, each holding a columnar base file plus a set of row-oriented
delta log files. When a streaming update arrives, Hudi's indexes locate the
file group that holds the record and *append* the change to that group's log
file. No base file is rewritten on the hot path — write amplification for a
file group is proportional to the records that changed, not the size of the
files they live in. Inserts ar [...]
+
+**Iceberg.** Iceberg's write path is snapshot-oriented: every commit adds new
immutable data files and produces a new snapshot — a new manifest list, new or
rewritten manifests, and a new table metadata file. For appends this is clean
and cheap per commit. For streaming upserts, Iceberg's merge-on-read mode
writes *delete files* alongside data files: equality deletes (typical for Flink
CDC pipelines) or position deletes mark old rows as superseded, and the new
values land in fresh data f [...]
+
+The structural difference: Hudi routes changes *into* an existing file-group
layout via its indexes and keeps files sized as it writes; Iceberg accretes new
files and metadata per commit and restores layout health through external
compaction.
+
+## Commit Cadence and Its Costs
+
+Consider what one day of minute-level commits — roughly 1,440 of them — does
to each format's metadata.
+
+In Hudi, each commit adds an entry to the [timeline](/docs/timeline), and
file-level statistics and listings land in Hudi's internal metadata table,
which is itself an MOR table designed to absorb frequent small mutations
cheaply. Older timeline entries are archived automatically into a compact
timeline history, so the active timeline that writers and readers consult stays
bounded no matter how long the pipeline runs. Frequent commits are the
*assumed* operating mode — the mechanisms tha [...]
+
+In Iceberg, each commit produces a new snapshot: a metadata JSON file, a
manifest list, and one or more manifests. At minute-level cadence, that is
1,440 snapshots a day, each retaining pointers to the manifests of its
predecessors until `expire_snapshots` runs. Manifests accumulate and fragment,
planning cost grows with manifest count, and the catalog's atomic pointer swap
becomes a serialization point that every commit contends on. None of this is a
correctness problem — Iceberg handle [...]
+
+The honest summary: both formats *can* commit every minute. Hudi's metadata
structures were designed around that rate; Iceberg's were designed around
fewer, larger commits, and sustained high cadence shifts real work onto the
maintenance schedule.
+
+## Keeping Readers Fast While Writing Continuously
+
+Log appends and delete files both defer merge work — the question is who pays
for it, and when.
+
+Hudi gives readers an explicit choice via its [query
types](/docs/table_types#query-types). *Snapshot queries* merge base files with
delta logs at read time and see the freshest data. *Read-optimized queries*
read only the compacted columnar base files, trading a bounded amount of
freshness for pure-Parquet scan performance. Async compaction runs continuously
in the background — scheduled and executed without pausing ingestion,
coordinated through MVCC on the timeline — so the merge debt [...]
+
+Iceberg readers on an upsert stream pay read amplification from delete files:
every scan of a data file must also apply the equality and position deletes
that reference it, until a compaction rewrites the affected files. There is no
built-in equivalent of the read-optimized query — the practical lever is
running `rewrite_data_files` (and delete-file compaction) often enough that
delete-file overhead stays tolerable. Format v3's deletion vectors improve the
mechanics of position deletes c [...]
+
+## Multi-Writer and Table Services Concurrency
+
+Streaming deployments rarely stay single-writer: a backfill job lands next to
the live pipeline, or compaction runs as a separate job from ingestion.
+
+Hudi's [concurrency control](/docs/concurrency_control) distinguishes writers
from table services. A single writer with async compaction, clustering, and
cleaning needs no external locks at all — MVCC coordinates ingestion and
services in-process, which covers the most common streaming deployment with
essentially zero concurrency configuration. For true multi-writer setups, Hudi
offers file-level optimistic concurrency control, and — for streaming semantics
— *non-blocking concurrency co [...]
+
+Iceberg uses optimistic concurrency for everything: each committer builds its
snapshot, then attempts an atomic pointer swap through the catalog; on conflict
it re-validates and retries. This is a clean, well-proven model, and for
writers touching disjoint files retries are cheap metadata operations. The
friction appears under sustained high commit rates: the ingestion job, the
compaction job, and the snapshot-expiry job are all competing committers to the
same table, and a long-running [...]
+
+## Engine Integrations for Streaming
+
+Both projects integrate with the major streaming engines, and it is worth
being factual rather than dismissive on either side.
+
+Iceberg has a mature Flink connector (checkpoint-aligned commits, upserts via
equality deletes), a Spark Structured Streaming sink, and a Kafka Connect sink.
For append-centric event pipelines at moderate checkpoint intervals, these work
well.
+
+Hudi's streaming surface is broader and more opinionated: the Flink writer
with async compaction in the same job, Spark Structured Streaming, the Kafka
Connect sink, and [Hudi Streamer](/docs/hoodie_streaming_ingestion) — a
complete ingestion utility with continuous mode, Kafka/DFS/CDC sources,
checkpoint management, and exactly-once delivery built in. The Flink
integration in particular has seen sustained recent investment: Hudi 1.1
[rebuilt the Flink write path around native RowData](/ [...]
+
+## A Decision Framework
+
+Setting aside benchmarks (run your own, on your workload), the architecture
suggests a straightforward split:
+
+- **Append-only event streams at moderate cadence** — clickstreams or logs
committed every 10–15 minutes, no updates. Either format works; Iceberg is a
perfectly good choice here, especially if your ecosystem is already
Iceberg-centric. Budget for scheduled compaction and snapshot expiry, and size
checkpoint intervals with metadata growth in mind.
+- **Upsert-heavy streams (CDC, mutable entities)** — this is where the
write-path difference compounds. Hudi's indexed log-append writes, delete
handling, and async compaction were built for exactly this pattern.
+- **Sub-10-minute freshness targets** — minute-level commit cadence plays to
Hudi's bounded timeline and mutation-friendly metadata table; on Iceberg it
demands a proportionally aggressive maintenance regimen.
+- **Hands-off operations** — if no team will babysit compaction schedules,
Hudi's self-managing posture (automatic file sizing at write time, async table
services inside the writer process) removes a whole category of orchestration.
+
+## It's Not Either/Or: Interoperability via Apache XTable
+
+The comparison above frames a *writer-side* decision — and it does not have to
constrain your readers. [Apache XTable](https://xtable.apache.org) (incubating)
translates table metadata between Hudi, Iceberg, and Delta Lake without copying
or rewriting data files. A common pattern is to ingest with Hudi — taking the
streaming-native write path, indexing, and async table services — and expose
the same data as an Iceberg table to catalogs and engines that expect Iceberg,
with metadata kept [...]
+
+## Conclusion
+
+Iceberg and Hudi are both capable, openly governed table formats, and both can
sit at the end of a streaming pipeline. The difference is what each was
designed to assume. Iceberg assumes commits are relatively infrequent and
maintenance runs between them; streaming is supported, and works, but small
files, delete files, and snapshot metadata become an operational program you
run alongside the pipeline. Hudi assumes the writers never stop: MOR log
appends keep update costs proportional to [...]
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+ {question: 'Can Apache Iceberg handle streaming writes?', answer: 'Yes.
Iceberg has a mature Flink connector, a Spark Structured Streaming sink, and a
Kafka Connect sink, and streaming appends work well at moderate commit cadence.
The caveat is operational: every commit creates a new snapshot with new
metadata and manifest files, and upserts add delete files that readers must
merge on every scan, so sustained high-frequency streaming requires regularly
scheduled compaction, manifest re [...]
+ {question: 'Why does Apache Hudi handle small files better than Iceberg?',
answer: 'Hudi addresses small files at write time rather than after the fact.
The writer automatically bin-packs new inserts against existing under-sized
file groups, so every commit works toward well-sized files, and updates are
appended to log files within existing file groups instead of creating new small
files. Iceberg writes new immutable files on every commit and relies on a
separately scheduled rewrite_da [...]
+ {question: 'Which table format works best with Apache Flink for streaming
ingestion?', answer: 'Both have solid Flink connectors, but Hudi offers a
deeper streaming integration: async compaction runs inside the same Flink job,
recent releases rebuilt the write path around Flink-native row types to cut
serialization overhead, and Hudi 1.2 added Record Level Index support so global
upsert lookups use the table-backed index instead of large Flink keyed state.
Iceberg Flink pipelines handl [...]
+ {question: 'Does frequent committing hurt Iceberg tables?', answer:
'Frequent commits are safe for correctness but costly operationally. Each
Iceberg commit produces a new metadata file, manifest list, and manifests, so
minute-level cadence yields well over a thousand snapshots per day whose
metadata accumulates until snapshot expiry runs, and concurrent committers
contend on the catalog pointer swap. This is why Iceberg streaming guidance
typically recommends longer checkpoint interva [...]
+ {question: 'Can I use Hudi for ingestion and still serve Iceberg readers?',
answer: 'Yes. Apache XTable (incubating) translates table metadata between
Hudi, Iceberg, and Delta Lake without copying or rewriting data files, either
as a one-time conversion or as continuous incremental sync. A common pattern is
to ingest with Hudi to get the streaming-native write path and async table
services, then expose the same data files as an Iceberg table to catalogs and
engines that expect Iceberg.'},
+]} />
diff --git
a/website/blog/2026-08-12-hudi-vs-delta-lake-for-write-heavy-workloads.md
b/website/blog/2026-08-12-hudi-vs-delta-lake-for-write-heavy-workloads.md
new file mode 100644
index 000000000000..72a8bba9e287
--- /dev/null
+++ b/website/blog/2026-08-12-hudi-vs-delta-lake-for-write-heavy-workloads.md
@@ -0,0 +1,120 @@
+---
+title: "Apache Hudi vs Delta Lake for Write-Heavy Workloads"
+excerpt: "A mechanism-level comparison of how Hudi and Delta Lake handle
update- and delete-heavy tables: indexing vs file-scan merge planning, MOR logs
vs Parquet rewrites, and how their costs scale as write rates climb."
+description: "How Apache Hudi and Delta Lake handle write-heavy workloads:
indexed upserts and MOR logs vs MERGE joins and file rewrites, compaction,
concurrency, streaming."
+authors: [sivabalan]
+category: deep-dive
+image:
/assets/images/blog/2024-05-27-apache-hudi-vs-delta-lake-choosing-the-right-tool-for-your-data-lake-on-aws.png
+tags:
+- comparison
+- delta lake
+- upsert
+- performance
+---
+
+For update- and delete-heavy tables, the core architectural difference is
this: Apache Hudi locates the records being changed through pluggable
[indexes](/docs/indexes) — including a record-level index that maps each key to
its file group — and can absorb changes into Merge-on-Read delta logs instead
of rewriting columnar files, while Delta Lake locates records by joining the
incoming batch against the table's data files (pruned by file statistics and,
more recently, softened by deletion [...]
+
+This post compares the two systems at the mechanism level: how each plans a
merge, what each does at write time, who cleans up afterward, and how they
behave under concurrency and streaming. It deliberately avoids benchmark
numbers — hardware, versions, and configurations change too fast for them to
stay honest — and focuses instead on the cost model each architecture implies.
+
+## What "Write-Heavy" Actually Means
+
+"Write-heavy" is not one workload; it is a cluster of characteristics that
stress a table format in different ways:
+
+- **High update/delete ratios.** The batch being written is mostly *changes to
existing records* rather than new inserts — CDC streams mirroring an OLTP
database, order-status updates, inventory corrections, GDPR deletes.
Insert-only workloads are easy for every format; it is mutation that separates
them.
+- **Frequent commits.** Writes land every few minutes (or faster) rather than
every few hours, so per-commit overheads — merge planning, file rewriting,
metadata churn — are paid dozens or hundreds of times a day.
+- **Random-key updates vs recent-partition updates.** If updates cluster in
the newest partitions (event tables), any format can prune its way to a small
working set. If updates scatter across the whole keyspace (dimension tables,
user profiles, unpartitioned tables), pruning breaks down and the mechanism for
*finding* records dominates cost.
+- **Concurrent writers.** Multiple pipelines — an ingestion job, a backfill, a
GDPR delete job — writing the same table at once, where conflict handling
decides how much work gets thrown away and retried.
+
+Keep these four dimensions in mind; the two systems diverge on each of them by
different amounts.
+
+## The MERGE Path, Compared
+
+**Delta Lake** expresses row-level mutation primarily through `MERGE INTO`.
The engine joins the source batch against the target table to identify which
data files contain matching rows, using file-level min/max statistics (and data
layout from Z-ordering or liquid clustering) to prune files where possible.
Matched files are then rewritten: a file containing even one matched row is
read, merged, and written out again as a new Parquet file. Deletion vectors
(Delta's merge-on-read-style fe [...]
+
+**Hudi** treats [upsert as a first-class write
operation](/docs/write_operations), not a SQL statement compiled into a join.
Incoming records carry a record key; the write path runs an [index
lookup](/docs/indexes) to tag each record as an insert or an update and route
it to the file group that already holds its key. What happens next depends on
the [table type](/docs/table_types): a Copy-on-Write (COW) table rewrites the
affected base files, much like Delta; a Merge-on-Read (MOR) table [...]
+
+The structural difference: Delta's merge planning cost lives in a join against
data files; Hudi's lives in an index lookup against metadata. As table size
grows and update keys scatter, the first grows with the table; the second grows
with the change batch (for non-global indexes) or stays a sharded point-lookup
(for the record-level index).
+
+## Indexing: The Core Difference
+
+Hudi maintains a persistent mapping from record keys to file groups and lets
you [pick the index](/docs/indexes) that matches your write pattern:
+
+- **Bloom index**: bloom filters plus key-range pruning, stored in file
footers or centrally in the metadata table. Excellent when keys have ordering
(e.g., timestamp-prefixed event keys), so most files are pruned before any data
is read.
+- **Record-level index (RLI)**: an exact key-to-file-group mapping in Hudi's
metadata table, hash-sharded for scale. It turns "which file holds this key?"
into a point lookup, which matters most on large tables with random-key updates
— precisely where probabilistic pruning fails.
+- **Bucket index**: hashes keys directly to file groups, eliminating the
lookup step entirely at the cost of a fixed (or consistent-hashed) bucket
layout. This is the workhorse for very high-throughput streaming upserts,
especially with Flink.
+- **Simple/global variants**: lean joins against existing keys, with global
versions that enforce uniqueness across partitions.
+
+Delta Lake's counterpart — and it is a real counterpart, not an absence — is
**data skipping**: per-file min/max statistics collected in the transaction
log, made more effective by clustering the data so related keys co-locate
(Z-ordering historically, liquid clustering more recently). When keys correlate
with layout, statistics prune candidate files well and MERGE touches little.
The honest framing is that Delta prunes *files by value ranges*, while Hudi
locates *records by key*. The fo [...]
+
+## Write Amplification and File Management
+
+Once records are located, the second question is how many bytes hit storage
per byte of change.
+
+On **Delta**, a MERGE that touches a file rewrites the file (deletion vectors
defer this, as noted). Write amplification is therefore proportional to the
number of *files* touched, and random small updates against large files are the
worst case. Compaction is handled by `OPTIMIZE` (with Z-order/clustering
options) and auto-compaction/optimized-writes features that coalesce small
files; on Databricks much of this is managed for you (predictive optimization),
while open-source deployments [...]
+
+On **Hudi**, a COW table has the same rewrite profile — with one mitigation:
Hudi's automatic file sizing packs inserts into under-sized file groups on
every write, keeping file counts and rewrite units under control without a
separate job. A MOR table changes the equation more fundamentally: updates are
appended to logs, so write amplification per commit is proportional to *records
changed*, not files touched; the rewrite cost is batched and amortized by
[compaction](/docs/compaction), [...]
+
+The operational difference is who runs the cleanup and whether writers wait
for it. Hudi ships cleaning, compaction, clustering, and file sizing as
self-managing services wired into the write path; Delta provides the
equivalents as commands and (on Databricks) managed features. For a write-heavy
table, the key property is that MOR moves the expensive columnar rewrite *off*
the ingestion path entirely — a batch of deletes trickling in all day can be
absorbed cheaply in logs and reconciled [...]
+
+## Concurrency Under Heavy Writes
+
+Both systems use optimistic concurrency control (OCC) between writers, and
both resolve conflicts at commit time — but the failure modes under heavy write
traffic differ.
+
+**Delta** detects conflicts by transaction-log versions: concurrent commits
that logically overlap (e.g., two MERGEs that may have read files the other
rewrote) surface as `ConcurrentAppend`/`ConcurrentDeleteRead`-class exceptions,
and the losing transaction retries. Partitioning and careful predicate scoping
reduce collisions, and this works well when writers touch disjoint partitions.
+
+**Hudi** offers file-level OCC with the same optimistic semantics (two writers
touching disjoint file groups both succeed), plus early conflict detection that
can abort a doomed writer mid-write rather than at commit, saving the wasted
compute. More distinctively, Hudi's [concurrency
model](/docs/concurrency_control) separates *writers* from *table services*:
compaction and clustering run under MVCC without competing in the OCC conflict
path, so a heavy ingestion writer is not fighting i [...]
+
+## Streaming Writes
+
+Both formats ingest from Spark Structured Streaming, and both can sustain
minute-level micro-batches. The differences are in what surrounds that path.
Hudi grew up as a streaming ingestion system (built at Uber to keep lake tables
in sync with upstream databases), and it shows in the toolchain: Hudi Streamer
is a ready-made continuous ingestion service with source connectors,
schema-registry integration, checkpointing, and async table services in one
process; MOR tables give streaming wr [...]
+
+For a dated but methodologically transparent data point on batch write/query
performance, see the 2022 [TPC-DS benchmark
comparison](/blog/2022/06/29/Apache-Hudi-vs-Delta-Lake-transparent-tpc-ds-lakehouse-performance-benchmarks)
— treat it strictly as a historical reference, since both systems have shipped
major releases since then.
+
+## A Decision Framework
+
+Delta Lake is a workable choice when:
+
+- You are **Databricks-centric** — the managed platform runs the
compaction/clustering machinery for you, and the ecosystem integration is
tightest there.
+- **Update rates are moderate** and mostly cluster in recent partitions, so
statistics-based pruning keeps MERGE cheap.
+- Your mutation pattern is **periodic batch MERGE** (hourly/daily), where
per-commit overhead is paid rarely.
+
+Hudi pulls ahead as workloads get write-heavier:
+
+- **Random-key upserts at scale** — dimension tables, user profiles,
unpartitioned tables — where the record-level or bucket index bounds locate
cost and MOR bounds rewrite cost.
+- **CDC replication** of operational databases, where upsert-as-a-primitive,
ordering-field-based merging of out-of-order events, and incremental pulls map
directly onto the problem.
+- **Sub-hour freshness targets** with frequent commits, where async compaction
keeps the ingestion path light.
+- **Open/non-Databricks deployments** — Spark, Flink, EMR, Dataproc, on-prem —
where Hudi's self-managing table services replace what a managed platform would
otherwise do for you.
+- **Multi-writer mutation**, where NBCC avoids OCC retry churn.
+
+## It's Not Either/Or: Interoperability via Apache XTable
+
+Choosing Hudi as the write layer does not cut you off from Delta-reading
tools. [Apache XTable](https://xtable.apache.org/) (incubating) translates
table metadata between Hudi, Delta Lake, and Iceberg over the *same* Parquet
data files — no data copying, just an additional metadata representation. You
can write with Hudi's indexed, MOR-backed ingestion path and expose the table
as Delta for Databricks SQL, or as Iceberg for engines that prefer it, keeping
a one-copy story much like Delta [...]
+
+## Conclusion
+
+Delta Lake and Apache Hudi can both run update-heavy tables; the question is
how their costs scale as "update-heavy" gets heavier. Delta plans merges by
joining against data files and applies them by rewriting Parquet — a model that
stays cheap while pruning works and update rates are moderate, and that
Databricks increasingly automates. Hudi plans merges through indexes and can
apply them as log appends — a model whose write cost tracks the size of the
change rather than the size of the [...]
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+ {
+ question: 'Is Hudi faster than Delta Lake for updates?',
+ answer: 'It depends on the update pattern, so be wary of any blanket
claim. For updates that scatter randomly across a large table, Hudi\'s
record-level and bucket indexes locate affected file groups without joining
against data files, and Merge-on-Read absorbs changes as log appends instead of
Parquet rewrites, which typically means lower write latency and less compute
per commit. For moderate update rates clustered in recent partitions, Delta\'s
statistics-based pruning keeps MERGE [...]
+ },
+ {
+ question: 'Does Delta Lake have an index?',
+ answer: 'Delta Lake does not maintain a record-level index that maps keys
to files. It relies on per-file min/max statistics in the transaction log for
data skipping, made more effective by clustering the data with Z-ordering or
liquid clustering, and deletion vectors reduce immediate file rewrites for
deletes and updates. This works well when update keys correlate with data
layout, but degrades toward scanning key columns across the table when updates
are random. Hudi instead mainta [...]
+ },
+ {
+ question: 'Can I use Apache Hudi outside Databricks?',
+ answer: 'Yes, and that is one of its main draws. Hudi is a community-run
Apache project that works with open-source Spark, Flink, Presto, Trino, and
cloud services like Amazon EMR, Google Dataproc, and AWS Glue, with no managed
platform required. Its table services, such as compaction, clustering,
cleaning, and file sizing, are built into the writers and run automatically,
covering the operational work a managed platform would otherwise do. Delta Lake
is also open source, but several [...]
+ },
+ {
+ question: 'What is the difference between Hudi Merge-on-Read and Delta
deletion vectors?',
+ answer: 'Both defer expensive file rewrites, but at different granularity.
Deletion vectors mark individual rows in a Parquet file as removed, so a delete
or update avoids an immediate rewrite, while the new version of an updated row
is still written to a data file and the marked file is eventually rewritten by
OPTIMIZE. Hudi\'s Merge-on-Read appends the full changed records to delta log
files attached to each file group, so arbitrary updates, not just row removals,
are absorbed chea [...]
+ },
+ {
+ question: 'Can Delta Lake tools read a Hudi table?',
+ answer: 'Yes, through Apache XTable, an incubating project that translates
table metadata between Hudi, Delta Lake, and Iceberg without copying data
files. You write with Hudi and run XTable sync to produce Delta transaction log
metadata over the same Parquet files, which Delta-compatible engines can then
read like any Delta table. This gives a one-copy, multi-format story similar to
Delta\'s UniForm feature, while keeping Hudi\'s indexing and Merge-on-Read
machinery on the write path.',
+ },
+]} />
diff --git a/website/blog/2026-08-13-hudi-vs-iceberg-performance-benchmarks.md
b/website/blog/2026-08-13-hudi-vs-iceberg-performance-benchmarks.md
new file mode 100644
index 000000000000..e7a45806fe7c
--- /dev/null
+++ b/website/blog/2026-08-13-hudi-vs-iceberg-performance-benchmarks.md
@@ -0,0 +1,109 @@
+---
+title: "Apache Hudi vs Apache Iceberg Performance: What Benchmarks Show, and
What We Measured"
+excerpt: "A Hudi maintainer's guide to the Hudi vs Iceberg benchmark record:
what published TPC-DS and upsert benchmarks show, plus reproducible LakeLoader
results for incremental writes."
+description: "What published Hudi vs Iceberg benchmarks show, why results
differ, reproducible LakeLoader incremental-write results, and how to run a
fair benchmark yourself."
+authors: [sivabalan]
+category: deep-dive
+image:
/assets/images/blog/2023-08-28-Delta-Hudi-Iceberg-A-Benchmark-Compilation.png
+tags:
+- comparison
+- apache iceberg
+- performance
+---
+
+If you searched "Hudi vs Iceberg performance benchmark" hoping for a single
number, here is the honest answer: no single published benchmark settles the
question, because results depend overwhelmingly on workload shape (append-only
scans versus update-heavy ingestion), on configuration parity between the
systems, and on the versions tested. What the record *does* show consistently
is that on read-dominated benchmarks like TPC-DS, table-format overheads
converge to within noise of each ot [...]
+
+This post is written from a Hudi maintainer's seat, so let us be direct about
the design-level conclusion we hold: **for incremental, update-heavy writes, we
believe Hudi will give you the best write performance of the major open table
formats.** Its record-level indexing and merge-on-read design bound write cost
to the size of the change rather than the size of the table, and its
concurrency model blocks writers less when table services run alongside
ingestion — a real advantage if you [...]
+
+## Why Lakehouse Benchmarks Are Hard to Get Right
+
+Table-format benchmarks are unusually easy to get wrong, and the failure modes
recur so reliably that they are worth naming up front.
+
+**Configuration parity is almost never achieved.** The formats ship with
different defaults because they optimize for different things. Hudi's default
write operation is `upsert`, which pays for index lookups and record merging so
mutations are cheap later; Iceberg and Delta default to append-style writes.
Benchmark a bulk load on defaults and you are not measuring format efficiency —
you are measuring whose defaults happen to match the workload. Vinoth Chandar's
April 2022 ["Corrections [...]
+
+**Default-versus-tuned is an editorial choice, not a neutral one.** Out of the
box, Hudi turns on table services and indexing that cost something at write
time and pay off at read and update time. A benchmark that measures only the
write pays the cost and never collects the payoff. Whether the right comparison
is "both on defaults" or "both tuned by experts" is a judgment call — a
credible benchmark states which it made and why.
+
+**Versions age fast.** Every benchmark below names specific versions — Hudi
0.11, Hudi 0.14, Delta 1.2 — that have since been superseded by releases with
materially different write paths (Hudi 1.x being the obvious example). A 2022
result is a historical data point, not a current one.
+
+**Provenance is context, not a verdict.** Most published lakehouse benchmarks
— including the ones in this post — come from people close to one of the
projects, because the people motivated to measure a system are usually the
people building on it. That is normal; it just means reproducibility is the
thing to check. Published code, configs, versions, and hardware let you verify
a result instead of taking it on trust, and that standard applies to our
numbers below as much as anyone else's.
+
+## What TPC-DS-Style Benchmarks Show
+
+TPC-DS is a decision-support benchmark: load the data once, then run about a
hundred analytical queries. It is scan- and query-dominated, which means it
exercises the part of a table format where the formats are most alike — listing
files, pruning with statistics, and reading Parquet.
+
+The most instructive public episode is from mid-2022. A benchmark by
Databeans, shown during a Databricks keynote, reported Hudi dramatically slower
than Delta and Iceberg on TPC-DS. Onehouse's June 2022 response, ["Transparent
TPC-DS Lakehouse Performance
Benchmarks"](/blog/2022/06/29/Apache-Hudi-vs-Delta-Lake-transparent-tpc-ds-lakehouse-performance-benchmarks)
by Alexey Kudinkin, re-ran the comparison on EMR 6.6.0 with Spark 3.2.0,
testing Hudi 0.11.1 against Delta 1.2.0 and 2.0.0rc1 [...]
+
+That episode is dated — those version numbers are ancient now — but its
structural finding has held: on read-heavy TPC-DS-style workloads, comparably
configured table formats land within noise of each other, because the query
engine and the Parquet scan dominate, not the table metadata layer. Kyle
Weller's 2023 compilation (next section) reached the same conclusion across
multiple 2022 TPC-DS runs, noting that Iceberg trailed in those particular
tests while Hudi and Delta were comparable [...]
+
+If TPC-DS is your workload — append-only loads, heavy analytical scans — the
published evidence says the format choice is unlikely to be your performance
bottleneck, and you should weigh operational and ecosystem factors instead.
+
+## What Mutation-Heavy Comparisons Show
+
+The picture inverts once the workload mutates data continuously, because now
the write path — how a format finds the records to update, absorbs deletes, and
amortizes merge costs — is the whole game, and here the formats differ
architecturally rather than cosmetically.
+
+The public record on this side is thinner but pointed. Kyle Weller's August
2023 ["Delta, Hudi, Iceberg — A Benchmark
Compilation"](/blog/2023/08/28/Delta-Hudi-Iceberg-A-Benchmark-Compilation)
recounts a Walmart Global Tech evaluation on two real production scenarios
rather than synthetic queries: a late-arriving-data workload with heavy
read/write amplification, and row-level upserts fed by CDC from Cassandra. In
Walmart's runs (on the then-current, now-old versions they tested), Delta [...]
+
+Why the divergence? Mechanism. To update a record, a writer must first find
it. Hudi ships a [multi-modal indexing subsystem](/docs/indexes) for exactly
this, and the impact of index choice alone is measurable: Soumil Shah's October
2023 [upsert evaluation on Hudi 0.14 with Spark
3.4.1](/blog/2023/10/29/UPSERT-Performance-Evaluation-of-Hudi-0-14-and-Spark-3-4-1-Record-Level-Index-Global-Bloom-Global-Simple-Indexes)
measured the same upsert workload under three of Hudi's global index opti [...]
+
+## The Benchmark Landscape, Compiled
+
+Weller's 2023 compilation remains the best single map of the public record. In
brief, the entries and their provenance:
+
+- **Databeans TPC-DS (June 2022)**, surfaced at a Databricks keynote; showed
Hudi far behind. Corrected by Onehouse for the configuration issues described
above; corrected results showed Hudi and Delta comparable, Iceberg trailing on
those versions.
+- **Brooklyn Data TPC-DS (2022)**, commissioned by Databricks covering Delta
and Iceberg; Onehouse extended it with Hudi. Same pattern on 2022 versions:
Hudi and Delta comparable, Iceberg slower in that run.
+- **Microsoft LST-Bench (paper published May 2023)**, a research effort
notable for methodology rather than a scoreboard: it extends TPC-DS with
mutations, concurrency, and maintenance phases, and proposes longevity metrics
— a direct acknowledgment that load-then-query benchmarks miss what matters for
these systems.
+- **Walmart Global Tech's production-scenario evaluation**, described above —
the clearest published mutation-heavy comparison, and the one whose results
diverge most sharply from the TPC-DS consensus.
+
+Where the results conflict — Iceberg competitive-to-trailing on scans in some
runs, not completing Walmart's write workloads — the conflict itself is the
finding: the benchmarks were measuring different mechanisms. Weller's own
bottom line is that performance benchmarks rarely represent real-life workloads
and users should run their own. We agree, and we took that advice ourselves.
+
+## What We Measured Ourselves: Incremental Writes with LakeLoader
+
+The biggest gap in the public record is mutation-heavy data on current
versions, so we ran our own comparison. All workloads used
[LakeLoader](https://github.com/onehouseinc/lake-loader), an open-source,
format-agnostic benchmarking framework that generates parameterized change
streams (scale, skew, update/insert mix) and applies identical rounds of
changes to each table format — the workload definition is shared across
systems, so differences in results come from the format's write path [...]
+
+In our runs, we observed:
+
+| Workload | What it models | What we observed |
+|---|---|---|
+| FACT, 10 TB, partitioned, skewed updates (Zipfian, 90% updates / 10%
inserts) | Time-partitioned fact tables (events, transactions) with
late-arriving updates | Hudi averaged ~4x lower incremental write latency than
Iceberg and ~6x lower than Delta Lake |
+| Merge-on-read, wide 100-column table, sparse partial updates (~20% of
columns per update) | Dimension tables — user profiles, account masters — where
updates touch a few columns | Hudi averaged ~8x lower steady-state latency than
Iceberg and ~5x lower than Delta Lake, by appending only column-level deltas |
+| Merge-on-read ingestion with concurrent async compaction | Streaming/CDC
pipelines with background maintenance under ingestion SLAs | Hudi sustained
continuous ingestion throughout; Iceberg and Delta Lake writes hit
snapshot-conflict retries during compaction windows |
+
+The mechanism behind the FACT numbers is the one this post keeps returning to:
Hudi's [record-level index](/docs/indexes) resolves which file groups each
batch touches directly, so per-commit shuffle stays on the order of the
incremental input (hundreds of megabytes in these runs), while the join-based
tagging paths in the other two formats scanned and shuffled hundreds of
gigabytes of the target table per commit. That is the same write-path
architecture difference the Walmart evaluation [...]
+
+Apply the same discipline to these numbers that this post asks of every other
benchmark. They are specific to these versions, this cluster shape, and these
workload parameters, and they say nothing about scan-heavy or append-only
workloads, where we expect the formats to land close together. The difference
is that you do not have to take our word for anything: the workload definitions
and run parameters live in LakeLoader, and you can rerun these workloads
yourself on your own hardware, [...]
+
+## How to Run a Benchmark That Actually Means Something
+
+The evergreen part of this post. If you benchmark Hudi against Iceberg for a
real decision, the published record suggests this checklist:
+
+1. **Benchmark your workload shape, not TPC-DS.** If your tables mutate, your
benchmark must mutate — run sustained upsert/delete phases against a loaded
table, not just the initial load.
+2. **Enforce configuration parity.** Same compression codec, same target file
sizes, same Spark/engine version and cluster. Use each format's *documented
recommendation* for the operation at hand (e.g., Hudi `bulk_insert` for
one-time loads, `upsert` for mutation phases).
+3. **State the index and delete strategy.** For Hudi, which index; for
Iceberg, copy-on-write vs merge-on-read and the delete-file mode. These are the
largest levers on the write path.
+4. **Include table-service costs.** Run compaction, clustering, and cleaning
inside the measured window — or report them separately — for both systems. A
write time that excludes the compaction it necessitates is fiction.
+5. **Separate cold and warm runs**, and run queries *during* and *after*
ingestion, not only on a freshly optimized table.
+6. **Measure over time, not one pass.** The LST-Bench insight: performance
after 100 commits differs from performance after one.
+7. **Publish versions, configs, and code.** If you cannot reproduce it,
neither can anyone who disagrees with it.
+
+## Questions to Ask of Any Published Benchmark
+
+The recurring gaps above explain most of the disagreement between published
results, so check for them systematically — in our numbers as much as anyone
else's. Were both systems given documented, workload-appropriate
configurations, or defaults for one and tuning for the other? Are versions
stated, and were they current at publication? Does a "write performance" test
include a sustained mutation phase, or only the initial load? Does the measured
window include the compaction the writes [...]
+
+## The Honest Bottom Line
+
+Choose by workload mechanism fit, then validate with your own benchmark. If
your workload is append-mostly analytics, the published record says format
overheads converge and your decision should rest on ecosystem, catalogs, and
operations. If it is mutation-heavy — CDC, streaming upserts, deletes at scale
— the write-path architecture differs materially, and the published record, the
design analysis, and our own reproducible runs all point the same way: Hudi's
indexed write path and non- [...]
+
+One more option the 2022-era benchmark wars did not have: you no longer have
to choose blind. [Apache XTable](https://xtable.apache.org) (incubating)
translates table metadata between Hudi and Iceberg without rewriting data
files, so you can write with one format and expose the other — or A/B both
against the same data — as described in [our XTable interoperability
post](/blog/2026/07/28/using-hudi-with-apache-iceberg-via-xtable).
+
+## Conclusion
+
+The published Hudi-versus-Iceberg record is smaller and older than the volume
of opinion written on top of it. What it supports: read-heavy benchmarks show
comparably configured formats within noise of each other (Onehouse, 2022, on
2022 versions); mutation-heavy evaluations show large, mechanism-driven
differences favoring purpose-built write paths (Walmart via Weller, 2023, on
the versions then tested); configuration parity gaps have distorted results in
both directions (Chandar, 2022) [...]
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+ {question: 'Is Apache Hudi faster than Apache Iceberg?', answer: 'For
incremental, update-heavy writes — CDC, streaming upserts, mutable tables — yes
in our reproducible runs: LakeLoader benchmarks on Spark 3.5 testing Hudi 1.1.1
against Iceberg 1.10.0 measured roughly 4x lower incremental write latency for
Hudi on a 10 TB skewed fact-table workload, driven by Hudi\'s record-level
index avoiding full-table-scan joins, with larger gaps on merge-on-read tables
with sparse column-level up [...]
+ {question: 'Why do Hudi vs Iceberg benchmark results disagree so much?',
answer: 'Because they measure different things under different conditions.
Scan-heavy benchmarks exercise the layer where the formats are most alike,
while update-heavy benchmarks exercise indexing, merge-on-read, and delete
handling, where they differ architecturally. Configuration disparities, such as
mismatched compression codecs or using Hudi\'s upsert where bulk_insert is
recommended, have also skewed publish [...]
+ {question: 'What is the best benchmark for comparing table formats?',
answer: 'One that matches your workload shape and is reproducible. TPC-DS alone
is a poor fit because it never mutates data after loading; Microsoft\'s
LST-Bench (2023) improves on it by adding mutation, concurrency, and
maintenance phases, and the open-source LakeLoader framework applies identical
parameterized change streams to each format for incremental-write comparisons.
The most meaningful test is your own pipe [...]
+ {question: 'Do Hudi\'s indexes really change upsert performance that much?',
answer: 'Yes, measurably. Soumil Shah\'s October 2023 evaluation on Hudi 0.14
found the record-level index roughly 45% faster than the global bloom index and
about 25% faster than the global simple index on the same upsert workload. That
within-format spread is why cross-format benchmarks that do not state their
index or delete-strategy configuration are hard to interpret meaningfully.'},
+ {question: 'Can I test both formats without maintaining two copies of my
data?', answer: 'Yes. Apache XTable (incubating) translates table metadata
between Hudi and Iceberg without rewriting the underlying data files, so you
can write with one format and query through the other, or run comparative tests
against the same physical data. That makes the format decision testable rather
than a leap of faith.'},
+]} />
diff --git
a/website/blog/2026-08-14-hudi-for-read-heavy-workloads-point-lookups-with-indexes.md
b/website/blog/2026-08-14-hudi-for-read-heavy-workloads-point-lookups-with-indexes.md
new file mode 100644
index 000000000000..b06a3e001d87
--- /dev/null
+++
b/website/blog/2026-08-14-hudi-for-read-heavy-workloads-point-lookups-with-indexes.md
@@ -0,0 +1,146 @@
+---
+title: "Point Lookups on the Lakehouse: How Hudi Indexes Accelerate Read-Heavy
Workloads"
+excerpt: "Partition pruning and min/max file statistics stop helping when
queries filter on high-cardinality columns. Hudi's record-level, secondary, and
expression indexes prune point lookups down to the handful of files that
actually contain matching rows."
+description: "How Apache Hudi's record-level, secondary, and expression
indexes prune files at query planning time to accelerate point lookups and
selective reads."
+authors: [sivabalan]
+category: deep-dive
+image:
/assets/images/blog/2024-03-30-record-level-indexing-apache-hudi-delivers-70-faster-point.png
+tags:
+- indexing
+- performance
+- querying
+- data skipping
+---
+
+Analytical scans are not the only workload a lakehouse table serves. In many
production query mixes, a large share of queries are needle-in-haystack reads:
fetch one order by `order_id`, pull a user's profile by `user_id`, trace a
request by `uuid`, list all events for one `customer_id`. These queries touch a
few rows out of billions — and they are exactly where the lake's two standard
pruning tools, partition pruning and min/max file statistics, stop helping.
Apache Hudi answers this wi [...]
+
+This post is the read-side companion to our [write-heavy
comparison](/blog/2026/08/12/hudi-vs-delta-lake-for-write-heavy-workloads).
Same approach: mechanisms first, and only benchmark numbers that have already
been published, with dates and sources.
+
+## Why Selective Queries Are Hard on a Data Lake
+
+Lakehouse tables are laid out for scans: large immutable columnar files,
grouped into partitions, described by file-level statistics. Every standard
read optimization prunes at one of those granularities, and each one has a
blind spot for selective predicates on high-cardinality columns:
+
+- **Partition pruning** only helps if the filter column is the partition
column. Nobody partitions by `user_id` or `uuid` — the cardinality is far too
high — so a point lookup on such a column matches *every* partition.
+- **Min/max file statistics** help when values correlate with file layout. A
filter on an ingestion timestamp prunes beautifully, because each file covers a
narrow time range. But a random key like a UUID is uniformly spread: every
file's min/max range spans nearly the whole keyspace, so every file "might"
contain the value and nothing is pruned. Sorting or clustering the data can
rescue statistics for *one* column, but a table can only be physically ordered
one way.
+- **Parquet footer bloom filters and page indexes** operate per file — the
engine still has to open every candidate file to consult them, which at
thousands of files is itself the bottleneck.
+
+The result is familiar to anyone who has run `SELECT * FROM events WHERE
request_id = '...'` on a large table: a full scan of the key column across the
table, minutes of compute, and (on scan-priced engines) a bill proportional to
table size rather than result size. What the query needed was a database-style
answer to "which files contain this value?" — an index.
+
+## How Hudi Indexes Serve Reads
+
+Hudi has maintained indexes since its inception, originally to make upserts
and deletes fast — the write side of the same problem, as covered in the
[write-heavy
post](/blog/2026/08/12/hudi-vs-delta-lake-for-write-heavy-workloads). With the
[multi-modal indexing subsystem](/docs/indexes#multi-modal-indexing), those
same structures are consulted at *query planning time*. The indexes live as
partitions of Hudi's metadata table — itself a Merge-on-Read Hudi table using
an HFile format optim [...]
+
+- **Record-level index (RLI)** — an exact mapping from record key to file
location, hash-sharded across file groups to scale to very large keyspaces. A
query with an equality predicate on the record key (`WHERE uuid = '...'`)
resolves directly to the file group holding that key; only that file is scanned.
+- **Secondary index** — introduced in [Hudi
1.0](/blog/2025/04/02/secondary-index), an index on any non-key column. It maps
secondary key values (e.g., `city`, `driver`, `customer_id`) to the record keys
that carry them; the record index then maps those keys to file locations.
Equality and `IN` predicates on indexed columns prune to exactly the files
containing matches.
+- **Expression index** — an index on a *function* of a column, in two flavors:
column-stats over transformed values (e.g., `from_unixtime(ts)` for date
filters on epoch columns) and bloom filters over transformed values for
equality matching on high-cardinality columns.
+- **Bloom filter index** — bloom filters for all data files stored centrally
in the metadata table, so candidate files can be eliminated without touching
each file's footer.
+- **Column stats and partition stats indexes** — the min/max statistics story,
but stored in the scalable metadata table and usable for range predicates and
partition-level skipping.
+
+The planning flow for a secondary-index lookup, as described in the [indexing
deep
dive](/blog/2025/11/12/deep-dive-into-hudis-indexing-subsystem-part-2-of-2):
the engine pushes the equality predicate down to Hudi's integration layer, the
secondary index returns the matching record keys, the record index returns the
enclosing file locations, and the engine plans a scan over just those files.
Two point lookups against compact metadata replace a scan over the table — the
same shape a datab [...]
+
+This combination of write-side and read-side indexing is one of the [things
that distinguish Hudi
architecturally](/blog/2025/03/05/hudi-21-unique-differentiators): the storage
format deliberately spends extra space on indexes to serve both record-level
mutation and selective reads, rather than optimizing for vanilla scans alone.
+
+## Using It from Spark SQL
+
+Index-accelerated reads are plain SQL. Create a table with the record index
enabled (secondary indexes require it, along with a primary key and the
`COMMIT_TIME_ORDERING` merge mode), then create indexes with `CREATE INDEX`:
+
+```sql
+CREATE TABLE hudi_table (
+ ts BIGINT,
+ uuid STRING,
+ rider STRING,
+ driver STRING,
+ fare DOUBLE,
+ city STRING
+) USING hudi
+OPTIONS (
+ primaryKey = 'uuid',
+ hoodie.metadata.record.index.enable = 'true',
+ hoodie.write.record.merge.mode = 'COMMIT_TIME_ORDERING'
+)
+PARTITIONED BY (city);
+
+-- record index first; secondary indexes build on it
+CREATE INDEX record_index ON hudi_table (uuid);
+-- secondary index on a non-key, high-cardinality column
+CREATE INDEX idx_rider ON hudi_table (rider);
+```
+
+Queries need no hints — equality predicates on indexed columns are pruned
automatically during planning:
+
+```sql
+-- point lookup on the record key, served by the record-level index
+SELECT * FROM hudi_table
+WHERE uuid = 'c8abbe79-8d89-47ea-b4ce-4d224bae5bfa';
+
+-- selective filter on a non-key column, served by the secondary index
+SELECT * FROM hudi_table WHERE rider = 'rider-B';
+```
+
+In the walkthrough in the [SQL queries documentation](/docs/sql_queries), the
second query scans one file instead of three after the index is created — on
the toy table that is the whole point demonstrated; on production tables the
pruning ratio scales with file count. Expression indexes cover predicates with
inline transformations, and bloom-filter expression indexes handle equality
matching where an exact mapping would be overkill:
+
+```sql
+-- date filters on an epoch column
+CREATE INDEX idx_column_ts ON hudi_table
+ USING column_stats(ts) OPTIONS(expr='from_unixtime', format='yyyy-MM-dd');
+
+-- bloom-filter pruning for equality predicates on driver
+CREATE INDEX idx_bloom_driver ON hudi_table
+ USING bloom_filters(driver) OPTIONS(expr='identity');
+```
+
+`SHOW INDEXES FROM hudi_table` lists what exists, `DROP INDEX` removes one,
and session settings such as `SET hoodie.metadata.record.index.enable=true` and
`SET hoodie.metadata.column.stats.enable=true` control which indexes the reader
consults — see [SQL queries](/docs/sql_queries) for the full set.
+
+## What About Trino?
+
+Honestly stated: index-based pruning through the record-level, secondary, and
expression indexes is a **Spark SQL capability today**. When secondary indexes
shipped in Hudi 1.0, [support was planned for Flink, Presto, and
Trino](/blog/2025/04/02/secondary-index) in a subsequent release; that work
rides on the fact that the indexes are engine-neutral storage structures —
partitions of the metadata table on disk, not Spark-private state — so an
engine integration implements the lookup agai [...]
+
+What Trino supports today, per the [query engine
documentation](/docs/sql_queries#trino): Hudi tables are queried through the
native Hudi connector (Trino 398 onward) or via the Hive connector with table
redirection (Trino 411 onward, using `hive.hudi-catalog-name=hudi`). Both paths
support snapshot queries on Copy-on-Write tables and read-optimized queries on
Merge-on-Read tables, with MOR snapshot query support in progress in the Trino
community. So a Trino-fronted deployment gets Hudi [...]
+
+## What Published Results Show
+
+Two data points, both from Hudi's own published material, both with setups
disclosed:
+
+- **Record-level index** ([indexing deep dive, November
2025](/blog/2025/11/12/deep-dive-into-hudis-indexing-subsystem-part-2-of-2)):
on a 400 GB synthetic Hudi table with 20,000 file groups, a query filtering on
a single record key dropped from 977 seconds to 12 seconds — a 98% reduction —
with the record index in use.
+- **Secondary index** ([secondary index announcement, April
2025](/blog/2025/04/02/secondary-index)): on the TPC-DS 1 TB dataset (Hudi
1.0.1, Spark 3.5.5 on EMR, 10 executors), a join query with a customer-id
lookup on `web_sales` ran ~33% faster on the first run and ~58% faster on a
warm second run with a secondary index on `ws_ship_customer_sk`. Data scanned
fell ~90% — from 67 GB across 5,000 files to 7 GB across 521 files, and from
719M rows scanned to 75M.
+
+The scan reduction is the number to internalize: latency gains vary with
cluster and cache state, but reading 90% fewer bytes is an architectural
outcome, and on engines priced per byte scanned it translates directly to cost.
For reproducing this class of measurement on your own keys and data
distribution, the open-source
[LakeLoader](https://github.com/onehouseinc/lake-loader) framework exists
precisely to generate controlled, repeatable lakehouse workloads.
+
+## How This Compares Architecturally
+
+Lakehouse table formats broadly take one of two positions on selective reads.
One position is *file-statistics-only pruning*: keep per-file min/max
statistics (plus partition values) in table metadata, and make them effective
by physically clustering data so that values correlate with files. This is
metadata that is cheap to maintain and works well when queries filter on the
clustering dimensions — but a table can only be clustered one way, and
predicates on other high-cardinality column [...]
+
+Hudi's position is *queryable index metadata*: spend additional storage and
write-path work maintaining exact value-to-location mappings (record-level and
secondary indexes) and auxiliary structures (bloom filters, expression indexes)
in a scalable, transactionally-updated metadata table, so that pruning for
equality predicates is an index lookup rather than a statistics estimate — on
as many columns as you choose to index. The trade is explicit: index storage
and maintenance cost in exc [...]
+
+## Operational Notes
+
+Two things keep this practical in production. First, indexes are maintained
**transactionally with each commit** — a query planned against the secondary
index sees results consistent with the latest completed write, not a lagging
sidecar. Second, adding an index to a table that is already ingesting does not
require stopping it: Hudi's [async indexing](/docs/metadata_indexing) builds a
new index in the background while writers keep committing, then reconciles the
seam — the mechanics and [...]
+
+## Conclusion
+
+Point lookups and selective filters on high-cardinality columns are a real,
often dominant slice of production query traffic, and they are precisely the
queries that partition pruning and min/max statistics cannot save. Hudi's
answer is the one databases settled on decades ago — indexes — rebuilt for lake
storage as transactional partitions of a scalable metadata table: a
record-level index for key equality, secondary indexes for non-key columns,
expression indexes for transformed predic [...]
+
+## FAQ
+
+<PostFAQ heading={null} items={[
+ {
+ question: 'Can you do point lookups on a data lake?',
+ answer: 'Yes, with a table format that maintains indexes. On a plain
columnar lake, a point lookup on a high-cardinality column degrades to scanning
that column across all files, because partition pruning and min/max statistics
cannot narrow random key values. Apache Hudi maintains a record-level index
mapping each record key to its file location and secondary indexes for non-key
columns inside its metadata table, so an equality predicate resolves to the few
files containing matches. [...]
+ },
+ {
+ question: 'What is a secondary index in Apache Hudi?',
+ answer: 'A secondary index, introduced in Hudi 1.0, is an index on any
column other than the record key. It stores mappings from secondary key values
to record keys in the metadata table; at query time the matched record keys are
resolved to file locations through the record-level index, and only those files
are scanned. It is created with plain SQL, for example CREATE INDEX idx_city ON
hudi_table(city), and requires the record index to be enabled on the table.',
+ },
+ {
+ question: 'Does Trino use Hudi indexes?',
+ answer: 'Not yet for record-level and secondary index pruning — that
acceleration is available from Spark SQL today. Trino queries Hudi tables
through the native Hudi connector or Hive connector redirection, supporting
snapshot queries on Copy-on-Write tables and read-optimized queries on
Merge-on-Read tables. Because Hudi\'s indexes are engine-neutral structures
stored in the metadata table rather than Spark-private state, engine
integrations can adopt them, and support for Presto, [...]
+ },
+ {
+ question: 'How much faster are queries with Hudi\'s indexes?',
+ answer: 'Per Hudi\'s published measurements: a record-key lookup on a 400
GB synthetic table with 20,000 file groups fell from 977 seconds to 12 seconds
with the record-level index (a 98% reduction), and a TPC-DS 1 TB join query
with a customer-id filter ran about 33-58% faster with a secondary index while
scanning roughly 90% less data — 7 GB across 521 files instead of 67 GB across
5,000 files. Actual gains depend on data distribution and cluster setup, so
test with your own workload.',
+ },
+ {
+ question: 'Does maintaining indexes for reads slow down ingestion?',
+ answer: 'Indexes are updated transactionally with each commit, which adds
bounded write-path work per index — one reason to index only the columns that
appear in selective predicates. Adding a new index to a live table does not
require stopping ingestion: Hudi\'s async indexing service builds the index in
the background while writers keep committing, then reconciles concurrent
changes, keeping the index timeline-consistent with the table.',
+ },
+]} />
diff --git a/website/static/llms.txt b/website/static/llms.txt
index f8fbfb4df255..f407d633bc50 100644
--- a/website/static/llms.txt
+++ b/website/static/llms.txt
@@ -59,6 +59,10 @@ It can also synchronize your data to half dozen data
catalogs to keep table cons
## Blog — Comparisons
- [Hudi vs Iceberg for CDC
Workloads](https://hudi.apache.org/blog/2026/08/06/hudi-vs-iceberg-for-cdc-workloads):
Criteria-driven comparison for change-data-capture ingestion.
+- [Hudi vs Iceberg for Streaming
Ingestion](https://hudi.apache.org/blog/2026/08/11/hudi-vs-iceberg-for-streaming-ingestion):
Which table format handles continuous, high-frequency writes better.
+- [Hudi vs Delta Lake for Write-Heavy
Workloads](https://hudi.apache.org/blog/2026/08/12/hudi-vs-delta-lake-for-write-heavy-workloads):
Update-intensive and mutable workloads compared across both formats.
+- [Hudi vs Iceberg Performance
Benchmarks](https://hudi.apache.org/blog/2026/08/13/hudi-vs-iceberg-performance-benchmarks):
A methodology-aware compilation of published benchmarks.
+- [Point Lookups on the
Lakehouse](https://hudi.apache.org/blog/2026/08/14/hudi-for-read-heavy-workloads-point-lookups-with-indexes):
How Hudi indexes accelerate read-heavy workloads and selective queries on
high-cardinality columns.
- [Hudi vs Delta Lake vs Iceberg Feature
Comparison](https://hudi.apache.org/blog/2023/01/11/Apache-Hudi-vs-Delta-Lake-vs-Apache-Iceberg-Lakehouse-Feature-Comparison):
Feature-by-feature comparison of the three open table formats.
## Blog — Deep dives