From 65f6fb8e94fdff217dcbc59cb1ae68c4c6c40f8c Mon Sep 17 00:00:00 2001 From: Alan Woodward Date: Fri, 17 Jul 2020 14:53:09 +0100 Subject: [PATCH] Shortcut mapping update if the incoming mapping version is the same as the current mapping version (#59517) (#59772) Currently, when we apply a cluster state change to a shard on a non-master node, we check to see if the mappings need to be updated by comparing the decompressed serialized mappings from the update against the serialized version of the shard's existing mappings. However, we already have a much simpler way of checking this, by comparing mapping versions on the index metadata of the old and new states. This commit adds a shortcut to MapperService.updateMappings() that compares these mapping versions, and ignores the merge if they are equal. --- .../index/mapper/MapperService.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java index 9324fb3157d..1ed225a7fdb 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -219,6 +219,12 @@ public class MapperService extends AbstractIndexComponent implements Closeable { public boolean updateMapping(final IndexMetadata currentIndexMetadata, final IndexMetadata newIndexMetadata) throws IOException { assert newIndexMetadata.getIndex().equals(index()) : "index mismatch: expected " + index() + " but was " + newIndexMetadata.getIndex(); + + if (currentIndexMetadata != null && currentIndexMetadata.getMappingVersion() == newIndexMetadata.getMappingVersion()) { + assertMappingVersion(currentIndexMetadata, newIndexMetadata, Collections.emptyMap()); + return false; + } + // go over and add the relevant mappings (or update them) Set existingMappers = new HashSet<>(); if (mapper != null) { @@ -230,7 +236,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { final Map updatedEntries; try { // only update entries if needed - updatedEntries = internalMerge(newIndexMetadata, MergeReason.MAPPING_RECOVERY, true); + updatedEntries = internalMerge(newIndexMetadata, MergeReason.MAPPING_RECOVERY); } catch (Exception e) { logger.warn(() -> new ParameterizedMessage("[{}] failed to apply mappings", index()), e); throw e; @@ -278,7 +284,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { private void assertMappingVersion( final IndexMetadata currentIndexMetadata, final IndexMetadata newIndexMetadata, - final Map updatedEntries) { + final Map updatedEntries) throws IOException { if (Assertions.ENABLED && currentIndexMetadata != null && currentIndexMetadata.getCreationVersion().onOrAfter(Version.V_6_5_0)) { @@ -302,10 +308,14 @@ public class MapperService extends AbstractIndexComponent implements Closeable { assert currentSource.equals(newSource) : "expected current mapping [" + currentSource + "] for type [" + mapping.type() + "] " + "to be the same as new mapping [" + newSource + "]"; + final CompressedXContent mapperSource = new CompressedXContent(Strings.toString(mapper)); + assert currentSource.equals(mapperSource) : + "expected current mapping [" + currentSource + "] for type [" + mapping.type() + "] " + + "to be the same as new mapping [" + mapperSource + "]"; } } else { - // if the mapping version is changed, it should increase, there should be updates, and the mapping should be different + // the mapping version should increase, there should be updates, and the mapping should be different final long currentMappingVersion = currentIndexMetadata.getMappingVersion(); final long newMappingVersion = newIndexMetadata.getMappingVersion(); assert currentMappingVersion < newMappingVersion : @@ -352,27 +362,19 @@ public class MapperService extends AbstractIndexComponent implements Closeable { } public void merge(IndexMetadata indexMetadata, MergeReason reason) { - internalMerge(indexMetadata, reason, false); + internalMerge(indexMetadata, reason); } public DocumentMapper merge(String type, CompressedXContent mappingSource, MergeReason reason) { return internalMerge(Collections.singletonMap(type, mappingSource), reason).get(type); } - private synchronized Map internalMerge(IndexMetadata indexMetadata, - MergeReason reason, boolean onlyUpdateIfNeeded) { + private synchronized Map internalMerge(IndexMetadata indexMetadata, MergeReason reason) { assert reason != MergeReason.MAPPING_UPDATE_PREFLIGHT; Map map = new LinkedHashMap<>(); for (ObjectCursor cursor : indexMetadata.getMappings().values()) { MappingMetadata mappingMetadata = cursor.value; - if (onlyUpdateIfNeeded) { - DocumentMapper existingMapper = documentMapper(mappingMetadata.type()); - if (existingMapper == null || mappingMetadata.source().equals(existingMapper.mappingSource()) == false) { - map.put(mappingMetadata.type(), mappingMetadata.source()); - } - } else { - map.put(mappingMetadata.type(), mappingMetadata.source()); - } + map.put(mappingMetadata.type(), mappingMetadata.source()); } return internalMerge(map, reason); }