Skip to content

Plan-time metadata-only DELETE: drop fully-covered data files from manifest bounds without scanning #1260

Description

@paultmathew

Summary

Add a plan-time optimization for DELETE where, if a DELETE's predicate provably covers all rows of a data file (from the file's partition and/or manifest column bounds), the file is dropped as a metadata-only delete — marked deleted in a new manifest — without scanning it and without writing a positional/equality delete file. Files only partially covered fall back to the existing scan + row-level delete path.

Motivation / why a new approach

I took a first cut at metadata-only deletes in #1178, but that PR resolves whole-file deletes at flush time — i.e., after the rows have already been scanned, once it observes that every live row of a file was deleted. In practice that path ended up entangled with manifest-rewrite / snapshot-summary / compaction-adjacent concerns, and the PR grew unwieldy without delivering the win that actually matters for large partitioned tables: not reading the data at all.

I'd like to step back and pursue the optimization at plan time instead, which is both more self-contained and where the real I/O savings are (e.g. DELETE ... WHERE dt = '2026-01-01' on a table partitioned by dt should touch zero data files).

Proposed approach

At DELETE planning, for each candidate data file:

  1. Evaluate the delete predicate against the file's partition values and manifest column bounds (lower/upper bounds, null counts).
  2. If the predicate provably selects every row of the file → drop the file metadata-only (new manifest entry marked DELETED), skip the scan.
  3. If the predicate provably selects no rows → prune the file entirely (no-op).
  4. Otherwise (partial / undecidable) → fall back to the current scan + row-level delete.

Relationship to #341

This is essentially the write-path counterpart to #341 ([Predicate Pushdown] Filtering deletes based on row counts). #341 asks "can this scan predicate match no rows of a delete file, so we can ignore it?"; this asks "does this delete predicate match all rows of a data file, so we can drop it whole?" Both need the same bounds-vs-predicate evaluator over manifest metrics — it would be worth sharing that machinery.

Scope / non-goals

  • In scope: the plan-time whole-file drop + fallback, using existing manifest partition/bounds metadata.
  • Non-goals: compaction / manifest rewriting, snapshot-summary accounting beyond what a normal delete already does, and equality-delete-file pruning on reads (that is [Predicate Pushdown] Filtering deletes based on row counts #341).

Open questions

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions