-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Concurrent Segment Search] Support parent-join aggregations #9316
Comments
This issue was originally created as a subtask for #7357 to focus on parent-join aggregation failure. Keep the original test failures below since the scope of the issue has expanded:
The |
I repurposed this issue as a backlog item to support parent-join aggregations in concurrent segment search and added all of my findings at the top level. I'll create another issue to track creating a dynamic cluster setting for disabling concurrent segment search for specific aggregators. In the meantime @reta @sohami would like to get your thoughts on the changes I suggested in the top level issue above (including if you agree with the new dynamic cluster setting). |
@jed326 Thanks for capturing the details here around parent-join aggregation. Would be great to verify and add a similar test case for child aggregation which fails with concurrent segment search.
+1. As you called out, setting based mechanism will be useful to disable for specific aggregations dynamically for subset of requests having such operations. Whereas other requests can still benefit from using concurrent search. We can definitely follow-up with the fixes for parent-join aggregation depending on the users interest and requirements. |
Added test cases as a part of #9446. A few things to note though:
|
The
join
field is a special field type that is used to create a relationship between documents in the same index. Parent and child documents must be indexed into the same shard to maintain the lineage relationship for aggregation purposes. Ref: https://opensearch.org/docs/latest/field-types/supported-field-types/join/For example, if there is a child document on
shard_0
and a parent document onshard_1
, then a parent aggregation would not collect any buckets because the relationship between the documents would not be found. In the case of concurrent segment search, this shard routing consideration leads to some similar problems.Focusing on the
ParentJoinAggregator
, this is a special type of aggregator:OpenSearch/modules/parent-join/src/main/java/org/opensearch/join/aggregations/ParentJoinAggregator.java
Lines 62 to 66 in bf10ff7
Specifically for
parent
aggregations, theinFilter
set is the child documents, while theoutFilter
set will be the parent documents. This is reversed forchildren
aggregations. Unlike other aggregators, duringLeafBucketCollector::colect
ParentJoinAggregator
does not collect the buckets. Instead it iterates through theinFilter
set and saves the globalOrdinal we are aggregating into aCollectionStrategy
object.OpenSearch/modules/parent-join/src/main/java/org/opensearch/join/aggregations/ParentJoinAggregator.java
Lines 118 to 127 in bf10ff7
Later at the beginning of the reduce phase
ParentJoinAggregator::beforeBuildingBuckets
is called which will iterate through theoutFilter
set and now we will collect buckets using the documents from theoutFilter
set that were saved inCollectionStrategy
.OpenSearch/modules/parent-join/src/main/java/org/opensearch/join/aggregations/ParentJoinAggregator.java
Lines 178 to 182 in bf10ff7
In the concurrent segment search path, there are 2 main problems with this approach.
CollectionStrategy
is created per-Aggregator instance, so it will not be shared across segment slices.CollectionStrategy
is basically what stores the relationship between parent and children docs, so it not being shared between segment slices means that we will not find the same relationships across segment slices.ParentJoinAggregator::beforeBuildingBuckets
iterates over all of the segments of the entire index.OpenSearch/modules/parent-join/src/main/java/org/opensearch/join/aggregations/ParentJoinAggregator.java
Lines 137 to 138 in bf10ff7
This means that we will call
collectBucket
for every segment slice where the relationship inCollectionStrategy
was found and lead to overcounting in most cases.Here are a few potential changes we can make:
To address problem 1:
CollectionStrategy
as a shared object between threads. This will lead to contention between the threads, especially if we implement it as a concurrent hash map and the data set is very low cardinality.LeafBucketCollector::collect
is called concurrently inindex_searcher
threads butParentJoinAggregator::beforeBuildingBuckets
is called sequentially for each aggregator in the reduce phase, we could merge together theCollectionStrategy
objects across the aggregators before we callaggregator.buildTopLevel()
inAggregationCollectorManager
.To address problem 2:
LeafReaderContext
that it as collected and in the reduce phase it will only evaluate those sameLeafReaderContext
s instead of all the leaves for the entire index.buildTopLevel
for a singleParentJoinAggregator
instance. This would work similar to howInternalAggregations::reduce
only calls reduce once here:OpenSearch/server/src/main/java/org/opensearch/search/aggregations/InternalAggregations.java
Line 186 in bf10ff7
Taking a step back, I think there is a broader problem that not all aggregation plugins may support concurrent search due to the nature of how they are implemented and if a user has a custom plugin that they have created they may want a way to not use concurrent search for their specific plugin. Off the top of my head, there could be other aggregation types that have shard routing considerations similar to this parent-join one or maybe there could be some arithmetic optimizations to an aggregation that specifically works better in the case of sequential searching. To address that I propose introducing a dynamic cluster setting that takes in a comma separated list of aggregator names that we would disable using concurrent search on.
In summary, these are the following changes I think we should make:
Aggregator
base classes to provide a new interface for doing the merge.The text was updated successfully, but these errors were encountered: