Skip to content

feat: rework SegmentFileBuilderV10 to organize internal containers by projection to be friendly to partial loading/eviction#19375

Open
clintropolis wants to merge 2 commits intoapache:masterfrom
clintropolis:segment-file-builder-v10-container-reorg
Open

feat: rework SegmentFileBuilderV10 to organize internal containers by projection to be friendly to partial loading/eviction#19375
clintropolis wants to merge 2 commits intoapache:masterfrom
clintropolis:segment-file-builder-v10-container-reorg

Conversation

@clintropolis
Copy link
Copy Markdown
Member

@clintropolis clintropolis commented Apr 24, 2026

Description

Rework SegmentFileBuilderV10 so V10 containers are scoped by a new declared file group concept instead of size alone. Groups provide a layout hint: a new container rolls when the declared group changes, giving readers a clean 1-to-N mapping between groups and containers that will support per-group partial loading in the future. Projections are the primary caller today, but the mechanism is deliberately generic (shared data across columns, internal metadata, etc.).

changes:

  • adds new method SegmentFileBuilder.startFileGroup(@Nullable String) which is a hint to the file builder about how to group the files a caller is adding
  • SegmentFileBuilderV10 replaced the internal FileSmoosher with a purpose-built container writer that rolls on group changes or when a file won't fit, organizing containers by the new file group concept
  • IndexMergerV10/IndexMergerBase use the new file group method to organize v10 segments by projection
  • removed stuff from FileSmoosher that was only needed by v10 builder delegating to it
  • AggregateProjectionSpec validates that the projection cannot be named __base

… projection to be friendly to partial loading

changes:
* adds new method `SegmentFileBuilder.startFileGroup(@nullable String)` which is a hint to the file builder about how to group the files a caller is adding
* `SegmentFileBuilderV10` replaced the internal `FileSmoosher` with a purpose-built container writer that rolls on group changes or when a file won't fit, organizing containers by the new file group concept
* `IndexMergerV10`/`IndexMergerBase` use the new file group method to organize v10 segments by projection
* removed stuff from `FileSmoosher` that was only needed by v10 builder delegating to it
* `AggregateProjectionSpec` validates that the projection cannot be named `__base`
this.file = file;
this.group = group;
this.maxSize = maxSize;
final FileOutputStream outStream = closer.register(new FileOutputStream(file));
@clintropolis clintropolis changed the title feat: rework SegmentFileBuilderV10 to organize internal containers by projection to be friendly to partial loading feat: rework SegmentFileBuilderV10 to organize internal containers by projection to be friendly to partial loading/eviction Apr 24, 2026
@FrankChen021
Copy link
Copy Markdown
Member

Findings that could not be attached inline:

  • processing/src/main/java/org/apache/druid/segment/file/SegmentFileBuilderV10.java:718 - P1 Delegated nested writes lose their file group. Nested addWithChannel calls are delegated while writerCurrentlyInUse is true, but mergeDelegatedFiles later replays those files with add(name, file) using whatever currentFileGroup is active at merge time. The original group active when the nested write was requested is not retained. If a nested file is created under one projection/container group and merged after the outer writer advances or clears the group, that nested file can be appended to the wrong container group, breaking the projection-to-container layout that partial loading depends on. Store the file group with each delegated temp file and restore/use it when merging.

Copy link
Copy Markdown
Contributor

@gianm gianm left a comment

Choose a reason for hiding this comment

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

Seems ok to me although I'm wondering about Frank's comment.

if (name == null || name.isEmpty()) {
throw InvalidInput.exception("projection name cannot be null or empty");
}
if (Projections.BASE_TABLE_PROJECTION_NAME.equals(name)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Might as well reserve all names starting with __, just in case we need another one later.

Copy link
Copy Markdown
Member Author

@clintropolis clintropolis Apr 27, 2026

Choose a reason for hiding this comment

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

done, moved to a method on Projections

@clintropolis
Copy link
Copy Markdown
Member Author

Seems ok to me although I'm wondering about Frank's comment.

Its like kind of real, but also maybe unlikely to ever happen in practice given standard uses of nested writers. The usage is like a column serializer is open and writing and needs to open a nested writer to write some of its parts to separate files which needs some temp files to do that get merged back in later. The problem described would occur only i think if someone closed the outer thingy but not the nested, then set a new group, then close the nested ones (which i'm not entirely sure how would occur with our current index merger paths). Nothing does this, because its pretty strange?

I went ahead and fixed the problem. Well, with the same limitations as the builder currently has here, that if the files aren't added to a group contiguously then they get stored in different containers, but it does at least ensure that containers have at most 1 group. So, if someone manages to do ^, it will put them into separate container associated with the group at the time of delegation instead of the current active group. 🤷

Copy link
Copy Markdown
Member

@FrankChen021 FrankChen021 left a comment

Choose a reason for hiding this comment

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

The changes LGTM, no correctness issues found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants