Jackie-Jiang opened a new pull request, #20077: URL: https://github.com/apache/pinot/pull/20077
## Summary The instance selectors keep a candidate list per segment, plus per-segment maps for new and unavailable segments, and recompute that per-segment state on every instance change. This PR indexes the state by candidate group instead: - Segments with the same candidates, of the same kind (old or new) and with the same number of expected replicas share one `CandidateGroup`. The per-segment state is one `int` group id, plus the creation time of new segments. - An instance change recomputes the routing of each group under the enabled instances, reusing the groups whose candidates did not change, and publishes it with the replica health in one immutable `SegmentStates`. - Selection builds the per-server `SegmentsToQuery` lists directly, presized from per-server hints. Estimated gains (compressed oops): - Selector state: ~81 to ~17 bytes per segment, ~64 MB less per million segments. New segments: ~255 to ~80 bytes. - Rebuild: no allocation per segment; candidates are computed once per distinct ideal state and external view pair. - Instance change: the cost depends on the number of groups, not segments. For 1M segments in 1K groups: ~8M hash operations and 40 MB of garbage become ~200 operations and 10 KB. - Query: 1 or 2 hash lookups per segment instead of 5 to 20, depending on the selector. ### Behavior changes - The segments of each server follow the order of the queried segments. - `SINGLE_POOL_SEGMENTS` (opt-in) is also emitted for strict replica-group, upsert and dedup tables. - The logs, `NO_SERVING_HOST_FOR_SEGMENT` and `SERVER_MISSING_FOR_ROUTING` are emitted once per group or server with the number of segments; the totals are unchanged. - The routing state and the replica health are published atomically, and a failed rebuild keeps the last good state. - The multi-stage selector reads the instance partitions once per query. - Fixed replica routing with `numReplicaGroupsToQuery` no longer fails when the table name hash overflows. ### Backward incompatible changes (custom instance selectors) - `InstanceSelector.select` takes a `Collection<String>`, and `SelectionResult` maps each server to its `SegmentsToQuery`; `InstanceMapping` is removed. - `BaseInstanceSelector` subclasses implement `select(Collection, int, SegmentStates, Map)` and return a `SelectionResult` built with a `SelectionCollector`. The protected per-segment maps, `putOldSegment` and `getNumInstancesOnlineForRouting` are removed, and `MAX_REQUEST_ID` is package-private. - `SegmentStates` has a package-private constructor, and resolves a segment through `getGroupId`, `getGroupRouting` and `isUnavailable`, replacing `getCandidates` and `getUnavailableSegments`. - `PriorityPoolInstanceSelector.select(ctx, candidates)` is replaced by `forQuery(ctx).select(candidates)`, which returns the index of the selected candidate. - `NewSegmentState` is removed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
