Skip to content

HBASE-29039 Seek past delete markers instead of skipping one at a time#8001

Open
junegunn wants to merge 1 commit intoapache:masterfrom
junegunn:HBASE-29039-alt
Open

HBASE-29039 Seek past delete markers instead of skipping one at a time#8001
junegunn wants to merge 1 commit intoapache:masterfrom
junegunn:HBASE-29039-alt

Conversation

@junegunn
Copy link
Copy Markdown
Member

@junegunn junegunn commented Mar 29, 2026

Context

HBASE-30036 (#7993) consolidates redundant delete markers on flush, preventing them from growing unbounded in HFiles. However, markers still accumulate in the memstore before flush, degrading read performance. HBASE-29039 addresses this from the read path side. Both are needed for full coverage. There is an open PR (#6557), but the review process has been stalled. This is an alternative approach with fewer code changes, hopefully making it easier to reach consensus.

Test result

Using the test code in HBASE-30036.

DeleteFamily

image
  • Substantial read performance improvement before flushes.
  • Without HBASE-30036, delete markers still accumulate in store files.

DeleteColumnContiguous

image
  • Substantial read performance improvement before flushes.
  • Without HBASE-30036, delete markers still accumulate in store files.

DeleteColumnInterleaved

image
  • No difference, as expected. Already triggers SEEK_NEXT_COL via the masked put.

Description

When a DeleteColumn or DeleteFamily marker is encountered during a normal user scan, the matcher currently returns SKIP, forcing the scanner to advance one cell at a time. This causes read latency to degrade linearly with the number of accumulated delete markers for the same row or column.

Since these are range deletes that mask all remaining versions of the column, seek past the entire column immediately via columns.getNextRowOrNextColumn(). This is safe because cells arrive in timestamp descending order, so any puts newer than the delete have already been processed.

For DeleteFamily, also fix getKeyForNextColumn in ScanQueryMatcher to bypass the empty-qualifier guard (HBASE-18471) when the cell is a DeleteFamily marker. Without this, the seek barely advances past the current cell instead of jumping to the first real qualified column.

The optimization is skipped when:

  • seePastDeleteMarkers is true (KEEP_DELETED_CELLS)
  • newVersionBehavior is enabled (sequence IDs determine visibility)
  • the delete marker is not tracked (visibility labels)

@junegunn junegunn marked this pull request as draft March 29, 2026 03:08
@junegunn
Copy link
Copy Markdown
Member Author

TestVisibilityLabelsWithDeletes is failing, which likely explains the additional changes in #6557. I'll try to fix it, but if it ends up resembling the previous approach, I'll drop this.

When a DeleteColumn or DeleteFamily marker is encountered during a normal
user scan, the matcher currently returns SKIP, forcing the scanner to
advance one cell at a time. This causes read latency to degrade linearly
with the number of accumulated delete markers for the same row or column.

Since these are range deletes that mask all remaining versions of the
column, seek past the entire column immediately via
columns.getNextRowOrNextColumn(). This is safe because cells arrive in
timestamp descending order, so any puts newer than the delete have
already been processed.

For DeleteFamily, also fix getKeyForNextColumn in ScanQueryMatcher to
bypass the empty-qualifier guard (HBASE-18471) when the cell is a
DeleteFamily marker. Without this, the seek barely advances past the
current cell instead of jumping to the first real qualified column.

The optimization is only applied with plain ScanDeleteTracker, and
skipped when:
- seePastDeleteMarkers is true (KEEP_DELETED_CELLS)
- newVersionBehavior is enabled (sequence IDs determine visibility)
- visibility labels are in use (delete/put label mismatch)
@junegunn
Copy link
Copy Markdown
Member Author

TestVisibilityLabelsWithDeletes is failing

Fixed by:

-          !seePastDeleteMarkers && !(deletes instanceof NewVersionBehaviorTracker)
+          !seePastDeleteMarkers && deletes.getClass() == ScanDeleteTracker.class

@junegunn junegunn marked this pull request as ready for review March 29, 2026 03:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant