Skip to content

perf(table): avoid cloning schema history for position_deletes partition IDs - #1920

Open
fallintoplace wants to merge 3 commits into
apache:mainfrom
fallintoplace:perf/avoid-position-delete-schema-history-clone
Open

perf(table): avoid cloning schema history for position_deletes partition IDs#1920
fallintoplace wants to merge 3 commits into
apache:mainfrom
fallintoplace:perf/avoid-position-delete-schema-history-clone

Conversation

@fallintoplace

Copy link
Copy Markdown
Contributor

What changed

  • Start synthetic position-delete partition field IDs at LastColumnID() + 1.
  • Keep the existing reserved-ID checks and partition-field remapping.
  • Avoid cloning and indexing every historical schema on each call.

Benchmark

  • Machine: Apple M1 Pro, darwin/arm64
  • Go: go1.26.3
  • Setup: 64 fields per schema; median of 5 runs
  • Command: go test ./table -run '^$' -bench '^BenchmarkPositionDeletesPartitionType/schemas=(1|16|128|1024)/fields=64$' -benchmem -count=5 -benchtime=1s
schemas ns/op B/op allocs/op
1 40,476 -> 18,736 100,368 -> 48,960 94 -> 56
16 347,383 -> 18,448 879,377 -> 48,960 570 -> 56
128 2,695,818 -> 18,115 6,692,085 -> 48,960 4,101 -> 56
1,024 20,795,189 -> 16,137 53,193,992 -> 48,960 32,328 -> 56

The optimized path is effectively flat as schema history grows.

Tests

  • Added coverage that the allocator does not request schema history.
  • Added coverage for skipping reserved IDs after LastColumnID().

@fallintoplace
fallintoplace force-pushed the perf/avoid-position-delete-schema-history-clone branch from 587588b to 29e119b Compare August 27, 2026 19:29

@zeroshade zeroshade left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The history-independent allocation is a substantial improvement, but the new starting-point calculation can produce duplicate or out-of-range field IDs.

Blocking — Guard synthetic field-ID allocation (table/inspect_position_deletes.go:817–831)

metadata.LastColumnID()+1 is used without validating it against the current schema or the signed 32-bit field-ID boundary.

I reproduced two regressions:

  1. The metadata parser accepts a schema field with ID 2 and last-column-id: 1. This change assigns the partition field ID 2, after which PositionDeletesSchema panics:

    invalid schema: multiple fields for id 2: x and x
    

    The merge-base implementation assigns an unused ID and succeeds.

  2. With LastColumnID() == iceberg.MaxStructFieldID and 193 active partition fields, the final generated ID is 2147483648, outside Iceberg’s signed 32-bit field-ID range. This also wraps on 32-bit platforms.

Please keep the fast path but seed collision checks from the current schema and make allocation overflow-safe. If the range above LastColumnID is exhausted, fall back to low unused IDs or return a structured error. Regression coverage should include both cases above.


This review was drafted by an AI-assisted tool and confirmed by an Iceberg Go maintainer. After you've addressed the points above and pushed an update, an Iceberg Go maintainer — a real person — will take the next look at the PR. The findings cite the project's review criteria; if you think one of them is mis-applied, please reply on the PR and a maintainer will weigh in.

More on how Iceberg Go handles maintainer review:
CONTRIBUTING.md.

@fallintoplace
fallintoplace force-pushed the perf/avoid-position-delete-schema-history-clone branch from 29e119b to f5052e8 Compare August 27, 2026 23:02
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.

2 participants