Browse Source

Cache resolved index for mgets (#101311)

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.
Daniel Mitterdorfer 1 year ago
parent
commit
95484b5936

+ 5 - 0
docs/changelog/101311.yaml

@@ -0,0 +1,5 @@
+pr: 101311
+summary: Cache resolved index for mgets
+area: CRUD
+type: enhancement
+issues: []

+ 11 - 4
server/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java

@@ -21,6 +21,7 @@ import org.elasticsearch.cluster.service.ClusterService;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.util.concurrent.AtomicArray;
 import org.elasticsearch.common.util.concurrent.AtomicArray;
 import org.elasticsearch.common.util.concurrent.EsExecutors;
 import org.elasticsearch.common.util.concurrent.EsExecutors;
+import org.elasticsearch.core.Tuple;
 import org.elasticsearch.index.shard.ShardId;
 import org.elasticsearch.index.shard.ShardId;
 import org.elasticsearch.indices.IndicesService;
 import org.elasticsearch.indices.IndicesService;
 import org.elasticsearch.tasks.Task;
 import org.elasticsearch.tasks.Task;
@@ -60,17 +61,23 @@ public class TransportMultiGetAction extends HandledTransportAction<MultiGetRequ
 
 
         final AtomicArray<MultiGetItemResponse> responses = new AtomicArray<>(request.items.size());
         final AtomicArray<MultiGetItemResponse> responses = new AtomicArray<>(request.items.size());
         final Map<ShardId, MultiGetShardRequest> shardRequests = new HashMap<>();
         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++) {
         for (int i = 0; i < request.items.size(); i++) {
             MultiGetRequest.Item item = request.items.get(i);
             MultiGetRequest.Item item = request.items.get(i);
 
 
             ShardId shardId;
             ShardId shardId;
             try {
             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()));
                 item.routing(clusterState.metadata().resolveIndexRouting(item.routing(), item.index()));
-                shardId = clusterService.operationRouting()
-                    .getShards(clusterState, concreteSingleIndex, item.id(), item.routing(), null)
-                    .shardId();
+                shardId = clusterService.operationRouting().shardId(clusterState, concreteSingleIndex, item.id(), item.routing());
             } catch (RoutingMissingException e) {
             } catch (RoutingMissingException e) {
                 responses.set(i, newItemFailure(e.getIndex().getName(), e.getId(), e));
                 responses.set(i, newItemFailure(e.getIndex().getName(), e.getId(), e));
                 continue;
                 continue;