Skip to content

Commit

Permalink
Cache resolved index for mgets
Browse files Browse the repository at this point in the history
Mgets need to resolve the provided index to an actual index. This is
done for every item in an mget request, even if all mgets target the
same index. With this commit we eliminate this overhead when only one
index (or a small number of indices with items sorted by index) is
affected.
  • Loading branch information
danielmitterdorfer committed Oct 25, 2023
1 parent 3031595 commit 73d7e9f
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.util.concurrent.AtomicArray;
import org.elasticsearch.common.util.concurrent.EsExecutors;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.tasks.Task;
Expand Down Expand Up @@ -60,16 +61,24 @@ protected void doExecute(Task task, final MultiGetRequest request, final ActionL

final AtomicArray<MultiGetItemResponse> responses = new AtomicArray<>(request.items.size());
final Map<ShardId, MultiGetShardRequest> shardRequests = new HashMap<>();
// single item cache that maps the provided index name to the resolved one
Tuple<String, String> lastResolvedIndex = Tuple.tuple(null, null);

for (int i = 0; i < request.items.size(); i++) {
MultiGetRequest.Item item = request.items.get(i);

ShardId shardId;
try {
String concreteSingleIndex = indexNameExpressionResolver.concreteSingleIndex(clusterState, item).getName();
String concreteSingleIndex;
if (item.index().equals(lastResolvedIndex.v1())) {
concreteSingleIndex = lastResolvedIndex.v2();
} else {
concreteSingleIndex = indexNameExpressionResolver.concreteSingleIndex(clusterState, item).getName();
lastResolvedIndex = Tuple.tuple(item.index(), concreteSingleIndex);
}
item.routing(clusterState.metadata().resolveIndexRouting(item.routing(), item.index()));
shardId = clusterService.operationRouting()
.getShards(clusterState, concreteSingleIndex, item.id(), item.routing(), null)
.getIndexShardRoutingTable(clusterState, concreteSingleIndex, item.id(), item.routing())
.shardId();
} catch (RoutingMissingException e) {
responses.set(i, newItemFailure(e.getIndex().getName(), e.getId(), e));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ void setUseAdaptiveReplicaSelection(boolean useAdaptiveReplicaSelection) {
this.useAdaptiveReplicaSelection = useAdaptiveReplicaSelection;
}

public IndexShardRoutingTable getIndexShardRoutingTable(
ClusterState clusterState,
String index,
String id,
@Nullable String routing
) {
IndexRouting indexRouting = IndexRouting.fromIndexMetadata(indexMetadata(clusterState, index));
return clusterState.getRoutingTable().shardRoutingTable(index, indexRouting.getShard(id, routing));
}

/**
* Shards to use for a {@code GET} operation.
* @return A shard iterator that can be used for GETs, or null if e.g. due to preferences no match is found.
Expand All @@ -67,8 +77,7 @@ public ShardIterator getShards(
@Nullable String routing,
@Nullable String preference
) {
IndexRouting indexRouting = IndexRouting.fromIndexMetadata(indexMetadata(clusterState, index));
IndexShardRoutingTable shards = clusterState.getRoutingTable().shardRoutingTable(index, indexRouting.getShard(id, routing));
IndexShardRoutingTable shards = getIndexShardRoutingTable(clusterState, index, id, routing);
return preferenceActiveShardIterator(shards, clusterState.nodes().getLocalNodeId(), clusterState.nodes(), preference, null, null);
}

Expand Down

0 comments on commit 73d7e9f

Please sign in to comment.