From ccaf846f1e917209adb15007add8085787f92e9f Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Fri, 26 Jun 2015 12:41:43 +0200 Subject: [PATCH] Store filter cache statistics at the shard level instead of index. Today we keep track of how often filters are used at the index level in order to decide whether they should be cached or not. This is an issue if you have several shards of the same index on the same node as it will multiply statistics by the number of shards that you have for this index on the node, which defeats the purpose of waiting for a filter to be reused before caching them. --- .../elasticsearch/index/cache/IndexCache.java | 9 +-------- .../index/cache/query/QueryCacheModule.java | 10 ---------- .../elasticsearch/index/shard/IndexShard.java | 17 ++++++++++++++--- .../org/elasticsearch/search/SearchService.java | 7 +++++-- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java b/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java index afb75cf50b5d0..0f2ace8c28b1f 100644 --- a/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java +++ b/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java @@ -19,7 +19,6 @@ package org.elasticsearch.index.cache; -import org.apache.lucene.search.QueryCachingPolicy; import org.apache.lucene.util.IOUtils; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; @@ -38,14 +37,12 @@ public class IndexCache extends AbstractIndexComponent implements Closeable { private final QueryCache queryCache; - private final QueryCachingPolicy queryCachingPolicy; private final BitsetFilterCache bitsetFilterCache; @Inject - public IndexCache(Index index, @IndexSettings Settings indexSettings, QueryCache queryCache, QueryCachingPolicy queryCachingPolicy, BitsetFilterCache bitsetFilterCache) { + public IndexCache(Index index, @IndexSettings Settings indexSettings, QueryCache queryCache, BitsetFilterCache bitsetFilterCache) { super(index, indexSettings); this.queryCache = queryCache; - this.queryCachingPolicy = queryCachingPolicy; this.bitsetFilterCache = bitsetFilterCache; } @@ -53,10 +50,6 @@ public QueryCache query() { return queryCache; } - public QueryCachingPolicy queryPolicy() { - return queryCachingPolicy; - } - /** * Return the {@link BitsetFilterCache} for this index. */ diff --git a/core/src/main/java/org/elasticsearch/index/cache/query/QueryCacheModule.java b/core/src/main/java/org/elasticsearch/index/cache/query/QueryCacheModule.java index 60288d99130e1..84030c0c69332 100644 --- a/core/src/main/java/org/elasticsearch/index/cache/query/QueryCacheModule.java +++ b/core/src/main/java/org/elasticsearch/index/cache/query/QueryCacheModule.java @@ -19,8 +19,6 @@ package org.elasticsearch.index.cache.query; -import org.apache.lucene.search.QueryCachingPolicy; -import org.apache.lucene.search.UsageTrackingQueryCachingPolicy; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.Scopes; import org.elasticsearch.common.settings.Settings; @@ -48,13 +46,5 @@ protected void configure() { bind(QueryCache.class) .to(settings.getAsClass(QueryCacheSettings.QUERY_CACHE_TYPE, IndexQueryCache.class, "org.elasticsearch.index.cache.query.", "QueryCache")) .in(Scopes.SINGLETON); - // the query cache is a node-level thing, however we want the most popular queries - // to be computed on a per-index basis, that is why we don't use the SINGLETON - // scope below - if (settings.getAsBoolean(QueryCacheSettings.QUERY_CACHE_EVERYTHING, false)) { - bind(QueryCachingPolicy.class).toInstance(QueryCachingPolicy.ALWAYS_CACHE); - } else { - bind(QueryCachingPolicy.class).toInstance(new UsageTrackingQueryCachingPolicy()); - } } } diff --git a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java index 39e82789bbdda..3a11dd64fbd85 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java +++ b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java @@ -24,6 +24,8 @@ import org.apache.lucene.codecs.PostingsFormat; import org.apache.lucene.index.CheckIndex; +import org.apache.lucene.search.QueryCachingPolicy; +import org.apache.lucene.search.UsageTrackingQueryCachingPolicy; import org.apache.lucene.store.AlreadyClosedException; import org.apache.lucene.util.IOUtils; import org.apache.lucene.util.ThreadInterruptedException; @@ -59,6 +61,7 @@ import org.elasticsearch.index.aliases.IndexAliasesService; import org.elasticsearch.index.cache.IndexCache; import org.elasticsearch.index.cache.bitset.ShardBitsetFilterCache; +import org.elasticsearch.index.cache.query.QueryCacheModule.QueryCacheSettings; import org.elasticsearch.index.cache.query.QueryCacheStats; import org.elasticsearch.index.cache.request.ShardRequestCache; import org.elasticsearch.index.codec.CodecService; @@ -242,7 +245,15 @@ public IndexShard(ShardId shardId, IndexSettingsService indexSettingsService, In this.checkIndexOnStartup = indexSettings.get("index.shard.check_on_startup", "false"); this.translogConfig = new TranslogConfig(shardId, shardPath().resolveTranslog(), indexSettings, getFromSettings(logger, indexSettings, Translog.Durabilty.REQUEST), bigArrays, threadPool); - this.engineConfig = newEngineConfig(translogConfig); + final QueryCachingPolicy cachingPolicy; + // the query cache is a node-level thing, however we want the most popular filters + // to be computed on a per-shard basis + if (indexSettings.getAsBoolean(QueryCacheSettings.QUERY_CACHE_EVERYTHING, false)) { + cachingPolicy = QueryCachingPolicy.ALWAYS_CACHE; + } else { + cachingPolicy = new UsageTrackingQueryCachingPolicy(); + } + this.engineConfig = newEngineConfig(translogConfig, cachingPolicy); this.indexShardOperationCounter = new IndexShardOperationCounter(logger, shardId); @@ -1336,7 +1347,7 @@ private Tuple docMapper(String type) { return mapperService.documentMapperWithAutoCreate(type); } - private final EngineConfig newEngineConfig(TranslogConfig translogConfig) { + private final EngineConfig newEngineConfig(TranslogConfig translogConfig, QueryCachingPolicy cachingPolicy) { final TranslogRecoveryPerformer translogRecoveryPerformer = new TranslogRecoveryPerformer(shardId, mapperService, queryParserService, indexAliasesService, indexCache) { @Override protected void operationProcessed() { @@ -1346,7 +1357,7 @@ protected void operationProcessed() { }; return new EngineConfig(shardId, threadPool, indexingService, indexSettingsService.indexSettings(), warmer, store, deletionPolicy, mergePolicyConfig.getMergePolicy(), mergeSchedulerConfig, - mapperService.indexAnalyzer(), similarityService.similarity(), codecService, failedEngineListener, translogRecoveryPerformer, indexCache.query(), indexCache.queryPolicy(), translogConfig); + mapperService.indexAnalyzer(), similarityService.similarity(), codecService, failedEngineListener, translogRecoveryPerformer, indexCache.query(), cachingPolicy, translogConfig); } private static class IndexShardOperationCounter extends AbstractRefCounted { diff --git a/core/src/main/java/org/elasticsearch/search/SearchService.java b/core/src/main/java/org/elasticsearch/search/SearchService.java index 45e69f56f8128..64b8b273ccae3 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchService.java +++ b/core/src/main/java/org/elasticsearch/search/SearchService.java @@ -27,6 +27,7 @@ import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.NumericDocValues; +import org.apache.lucene.search.QueryCachingPolicy; import org.apache.lucene.search.TopDocs; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchParseException; @@ -373,8 +374,9 @@ public QuerySearchResult executeQueryPhase(QuerySearchRequest request) { contextProcessing(context); try { final IndexCache indexCache = context.indexShard().indexService().cache(); + final QueryCachingPolicy cachingPolicy = context.indexShard().engine().config().getQueryCachingPolicy(); context.searcher().dfSource(new CachedDfSource(context.searcher().getIndexReader(), request.dfs(), context.similarityService().similarity(), - indexCache.query(), indexCache.queryPolicy())); + indexCache.query(), cachingPolicy)); } catch (Throwable e) { processFailure(context, e); cleanContext(context); @@ -447,8 +449,9 @@ public QueryFetchSearchResult executeFetchPhase(QuerySearchRequest request) { contextProcessing(context); try { final IndexCache indexCache = context.indexShard().indexService().cache(); + final QueryCachingPolicy cachingPolicy = context.indexShard().engine().config().getQueryCachingPolicy(); context.searcher().dfSource(new CachedDfSource(context.searcher().getIndexReader(), request.dfs(), context.similarityService().similarity(), - indexCache.query(), indexCache.queryPolicy())); + indexCache.query(), cachingPolicy)); } catch (Throwable e) { freeContext(context.id()); cleanContext(context);