fix(upsert): bound file match filter to avoid segfault#3420
Open
abnobdoss wants to merge 1 commit into
Open
Conversation
|
This pull request has been marked as stale due to 30 days of inactivity. It will be closed in 1 week if no further activity occurs. If you think that's incorrect or this pull request requires a review, please simply write any comment. If closed, you can revive the PR at any time and @mention a reviewer or discuss it on the dev@iceberg.apache.org list. Thank you for your contributions. |
Contributor
Author
|
Still active - happy to address any feedback. |
|
Are there any updates on this? Has the issue been resolved? I noticed there are two PRs, but neither has been merged yet. Could someone provide some clarification on the current status? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rationale for this change
Upserts with large composite (multi-column) keys segfault during scan planning. The initial scan builds one
And(EqualTo, EqualTo)per unique source key andOrs them into a deep tree, which PyArrow's C++ engine recurses over inGetFragments→Canonicalize, overflowing the C stack (SIGSEGV) at tens of thousands of keys.This PR uses a bounded
create_file_match_filterfor the initial file-pruning scan: per-column min/max bounds (plusIsNullwhere needed), so predicate size scales with the number of join columns, not source rows. The exactcreate_match_filteris still used downstream for overwrite and insert filtering, so row-level correctness is unchanged.The bounds are loose by design. With composite keys they can pull in false positives, but exact matching drops those before anything is written, so the only cost is scanning a few extra files in exchange for upserts that no longer crash. A follow-up could tighten this, for example per-prefix bounds or a grouped
In, as long as the predicate size stays bounded.Benchmarks
Timings cover expression construction, schema binding, PyArrow conversion, and applying the resulting Arrow filter to an in-memory table. They do not measure end-to-end upsert time, which also depends on table layout, file pruning, IO, and downstream exact matching. Benchmark script.
Before, exact match-filter path:
After, bounded file-match filter path:
Related
BooleanExpressionincreate_match_filterbefore any IO. This PR replaces that pre-IO full-source predicate with the bounded filter. The overwrite and insert predicates are still exact and unchanged.create_match_filterandtxn.delete()performance #3129: large-upsert performance. Removes the full-sourcecreate_match_filtercall fromupsert(). Does not change thetxn.delete()path or the directcreate_match_filteruse in that report's flow.Are these changes tested?
Yes. Added coverage for bounded-filter construction, the false-positive culling path, and a large composite-key regression test. The regression test runs the upsert in a subprocess, so a runtime that would segfault reports a pytest failure instead of killing the worker: the base branch exits 139 under Python 3.10, and this branch exits 0.
Ran:
uv run python -m pytest tests/table/test_upsert.py -k "large_composite_key_initial_scan or file_match_filter or create_match_filter"uv run python -m pytest tests/table/test_upsert.pyAre there any user-facing changes?
No API changes. Large composite-key upserts no longer crash during initial scan planning, and may scan a conservative superset of candidate files before exact row matching.