advanced 2 min answer Multiple choice

A ride-hailing company in the mould of Uber upserts trip state into a lake table: 8 million row updates an hour spread across the last 3 days of partitions, with dashboards that tolerate 5 minutes of staleness. Compaction runs hourly. Which table layout should the team choose?

apache hudicopy-on-writemerge-on-readupsertswrite amplificationuber
Pick one
Show the full answer Hide the answer

The deciding property

The update pattern is wide and frequent, so write amplification, not read speed, is the binding constraint. Eight million updates an hour hit a small fraction of rows in each of thousands of files. Copy-on-write must rewrite every file containing even one changed row.

The numbers

Suppose each file is 256 MB and holds about 1 million rows, and the 3-day window holds roughly 300 files (300 million rows). Eight million updates an hour spread across 300 files is about 27,000 updates per file, so every file in the window is touched every hour. Copy-on-write then rewrites about 77 GB (300 x 256 MB) to land roughly 1.6 GB of logical change (8 million rows at ~200 bytes). That is write amplification near 50x, and it repeats 24 times a day.

Merge-on-read writes the changes to small delta files next to the base files and merges them at read time or during compaction. The commit cost tracks the size of the change. Apache Hudi, created at Uber to make incremental upserts on HDFS cheap (Uber described it publicly in 2017), exposes exactly this choice as its two table types.

Why not the others

  • Copy-on-write is the right answer when updates are rare or clustered: nightly dimension corrections that touch 0.1% of files, where read simplicity (plain columnar files, no merge) is worth the occasional rewrite.
  • Append-only plus a latest-row view moves the cost to every query. Each read must deduplicate by key over all versions, and the version count grows until compaction, which is the same work moved to the worst moment.
  • Hourly partition overwrite is copy-on-write with coarser granularity and a wider blast radius; a failed overwrite leaves three days of data inconsistent.

What merge-on-read costs

Reads that merge unfinished deltas are slower, and the penalty grows if compaction lags. Operationally the team now owns a compaction service and a lag metric (delta files per file group); a stalled compaction silently turns a fast table into a slow one. Engines also differ in whether they can read the merged view, so check every consumer before choosing.

What would flip it

If this changes Choose Because
Updates fall below ~1% of files per hour Copy-on-write Rewrite cost is small and reads stay simple
Dashboards need sub-second reads on fresh rows Copy-on-write or a serving store Merge cost lands on the read path
Updates arrive as a stream of deletes Merge-on-read with deletion files Cheap row-level removal

Where copying this is a mistake

A team with a daily batch and a single-digit-GB table gains nothing from either layout. Plain partition overwrite is simpler and has no compaction service to run.

Common weak answers

  • "Merge-on-read is faster." It is faster to write and slower to read; the question is which side the workload can afford.
  • "Always copy-on-write, it is simpler." Simple until commits take longer than the commit interval.