Allow the query cache to be disabled. #16268
This replaces the internal `index.queries.cache.type` setting with a new `index.queries.cache.enabled` setting, which is documented. Closes #15802
This commit is contained in:
parent
dd8afc9567
commit
0eb1a816c8
|
@ -132,7 +132,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
|
|||
MapperService.INDEX_MAPPING_DEPTH_LIMIT_SETTING,
|
||||
BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING,
|
||||
IndexModule.INDEX_STORE_TYPE_SETTING,
|
||||
IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING,
|
||||
IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING,
|
||||
IndexModule.INDEX_QUERY_CACHE_EVERYTHING_SETTING,
|
||||
PrimaryShardAllocator.INDEX_RECOVERY_INITIAL_SHARDS_SETTING,
|
||||
FsDirectoryService.INDEX_LOCK_FACTOR_SETTING,
|
||||
|
|
|
@ -27,8 +27,8 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.env.NodeEnvironment;
|
||||
import org.elasticsearch.index.analysis.AnalysisRegistry;
|
||||
import org.elasticsearch.index.cache.query.QueryCache;
|
||||
import org.elasticsearch.index.cache.query.index.IndexQueryCache;
|
||||
import org.elasticsearch.index.cache.query.none.NoneQueryCache;
|
||||
import org.elasticsearch.index.cache.query.IndexQueryCache;
|
||||
import org.elasticsearch.index.cache.query.DisabledQueryCache;
|
||||
import org.elasticsearch.index.engine.EngineFactory;
|
||||
import org.elasticsearch.index.shard.IndexEventListener;
|
||||
import org.elasticsearch.index.shard.IndexSearcherWrapper;
|
||||
|
@ -75,14 +75,15 @@ public final class IndexModule {
|
|||
public static final Setting<String> INDEX_STORE_TYPE_SETTING =
|
||||
new Setting<>("index.store.type", "", Function.identity(), Property.IndexScope, Property.NodeScope);
|
||||
public static final String SIMILARITY_SETTINGS_PREFIX = "index.similarity";
|
||||
public static final String INDEX_QUERY_CACHE = "index";
|
||||
public static final String NONE_QUERY_CACHE = "none";
|
||||
public static final Setting<String> INDEX_QUERY_CACHE_TYPE_SETTING =
|
||||
new Setting<>("index.queries.cache.type", INDEX_QUERY_CACHE, Function.identity(), Property.IndexScope);
|
||||
|
||||
// whether to use the query cache
|
||||
public static final Setting<Boolean> INDEX_QUERY_CACHE_ENABLED_SETTING =
|
||||
Setting.boolSetting("index.queries.cache.enabled", true, Property.IndexScope);
|
||||
|
||||
// for test purposes only
|
||||
public static final Setting<Boolean> INDEX_QUERY_CACHE_EVERYTHING_SETTING =
|
||||
Setting.boolSetting("index.queries.cache.everything", false, Property.IndexScope);
|
||||
|
||||
private final IndexSettings indexSettings;
|
||||
private final IndexStoreConfig indexStoreConfig;
|
||||
private final AnalysisRegistry analysisRegistry;
|
||||
|
@ -92,8 +93,7 @@ public final class IndexModule {
|
|||
private final Set<IndexEventListener> indexEventListeners = new HashSet<>();
|
||||
private final Map<String, BiFunction<String, Settings, SimilarityProvider>> similarities = new HashMap<>();
|
||||
private final Map<String, BiFunction<IndexSettings, IndexStoreConfig, IndexStore>> storeTypes = new HashMap<>();
|
||||
private final Map<String, BiFunction<IndexSettings, IndicesQueryCache, QueryCache>> queryCaches = new HashMap<>();
|
||||
private final SetOnce<String> forceQueryCacheType = new SetOnce<>();
|
||||
private final SetOnce<BiFunction<IndexSettings, IndicesQueryCache, QueryCache>> forceQueryCacheProvider = new SetOnce<>();
|
||||
private final List<SearchOperationListener> searchOperationListeners = new ArrayList<>();
|
||||
private final List<IndexingOperationListener> indexOperationListeners = new ArrayList<>();
|
||||
private final AtomicBoolean frozen = new AtomicBoolean(false);
|
||||
|
@ -102,8 +102,6 @@ public final class IndexModule {
|
|||
this.indexStoreConfig = indexStoreConfig;
|
||||
this.indexSettings = indexSettings;
|
||||
this.analysisRegistry = analysisRegistry;
|
||||
registerQueryCache(INDEX_QUERY_CACHE, IndexQueryCache::new);
|
||||
registerQueryCache(NONE_QUERY_CACHE, (a, b) -> new NoneQueryCache(a));
|
||||
this.searchOperationListeners.add(new SearchSlowLog(indexSettings));
|
||||
this.indexOperationListeners.add(new IndexingSlowLog(indexSettings));
|
||||
}
|
||||
|
@ -235,22 +233,6 @@ public final class IndexModule {
|
|||
similarities.put(name, similarity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link QueryCache} provider for a given name
|
||||
* @param name the providers / caches name
|
||||
* @param provider the provider instance
|
||||
*/
|
||||
public void registerQueryCache(String name, BiFunction<IndexSettings, IndicesQueryCache, QueryCache> provider) {
|
||||
ensureNotFrozen();
|
||||
if (provider == null) {
|
||||
throw new IllegalArgumentException("provider must not be null");
|
||||
}
|
||||
if (queryCaches.containsKey(name)) {
|
||||
throw new IllegalArgumentException("Can't register the same [query_cache] more than once for [" + name + "]");
|
||||
}
|
||||
queryCaches.put(name, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a {@link org.elasticsearch.index.IndexModule.IndexSearcherWrapperFactory} that is called once the IndexService
|
||||
* is fully constructed.
|
||||
|
@ -331,26 +313,33 @@ public final class IndexModule {
|
|||
indexSettings.getScopedSettings().addSettingsUpdateConsumer(IndexStore.INDEX_STORE_THROTTLE_TYPE_SETTING, store::setType);
|
||||
indexSettings.getScopedSettings().addSettingsUpdateConsumer(IndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC_SETTING,
|
||||
store::setMaxRate);
|
||||
final String queryCacheType = forceQueryCacheType.get() != null
|
||||
? forceQueryCacheType.get() : indexSettings.getValue(INDEX_QUERY_CACHE_TYPE_SETTING);
|
||||
final BiFunction<IndexSettings, IndicesQueryCache, QueryCache> queryCacheProvider = queryCaches.get(queryCacheType);
|
||||
final QueryCache queryCache = queryCacheProvider.apply(indexSettings, indicesQueryCache);
|
||||
final QueryCache queryCache;
|
||||
if (indexSettings.getValue(INDEX_QUERY_CACHE_ENABLED_SETTING)) {
|
||||
BiFunction<IndexSettings, IndicesQueryCache, QueryCache> queryCacheProvider = forceQueryCacheProvider.get();
|
||||
if (queryCacheProvider == null) {
|
||||
queryCache = new IndexQueryCache(indexSettings, indicesQueryCache);
|
||||
} else {
|
||||
queryCache = queryCacheProvider.apply(indexSettings, indicesQueryCache);
|
||||
}
|
||||
} else {
|
||||
queryCache = new DisabledQueryCache(indexSettings);
|
||||
}
|
||||
return new IndexService(indexSettings, environment, new SimilarityService(indexSettings, similarities), shardStoreDeleter,
|
||||
analysisRegistry, engineFactory.get(), servicesProvider, queryCache, store, eventListener, searcherWrapperFactory,
|
||||
mapperRegistry, indicesFieldDataCache, searchOperationListeners, indexOperationListeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces a certain query cache type. If this is set
|
||||
* the given cache type is overriding the default as well as the type
|
||||
* set on the index level.
|
||||
* Forces a certain query cache to use instead of the default one. If this is set
|
||||
* and query caching is not disabled with {@code index.queries.cache.enabled}, then
|
||||
* the given provider will be used.
|
||||
* NOTE: this can only be set once
|
||||
*
|
||||
* @see #INDEX_QUERY_CACHE_TYPE_SETTING
|
||||
* @see #INDEX_QUERY_CACHE_ENABLED_SETTING
|
||||
*/
|
||||
public void forceQueryCacheType(String type) {
|
||||
public void forceQueryCacheProvider(BiFunction<IndexSettings, IndicesQueryCache, QueryCache> queryCacheProvider) {
|
||||
ensureNotFrozen();
|
||||
this.forceQueryCacheType.set(type);
|
||||
this.forceQueryCacheProvider.set(queryCacheProvider);
|
||||
}
|
||||
|
||||
private void ensureNotFrozen() {
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.cache.query.none;
|
||||
package org.elasticsearch.index.cache.query;
|
||||
|
||||
import org.apache.lucene.search.QueryCachingPolicy;
|
||||
import org.apache.lucene.search.Weight;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.index.AbstractIndexComponent;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.cache.query.QueryCache;
|
||||
|
@ -29,9 +28,9 @@ import org.elasticsearch.index.cache.query.QueryCache;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class NoneQueryCache extends AbstractIndexComponent implements QueryCache {
|
||||
public class DisabledQueryCache extends AbstractIndexComponent implements QueryCache {
|
||||
|
||||
public NoneQueryCache(IndexSettings indexSettings) {
|
||||
public DisabledQueryCache(IndexSettings indexSettings) {
|
||||
super(indexSettings);
|
||||
logger.debug("Using no query cache");
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.cache.query.index;
|
||||
package org.elasticsearch.index.cache.query;
|
||||
|
||||
import org.apache.lucene.search.QueryCachingPolicy;
|
||||
import org.apache.lucene.search.Weight;
|
|
@ -30,6 +30,7 @@ import org.apache.lucene.search.TermStatistics;
|
|||
import org.apache.lucene.search.Weight;
|
||||
import org.apache.lucene.search.similarities.BM25Similarity;
|
||||
import org.apache.lucene.search.similarities.Similarity;
|
||||
import org.apache.lucene.util.SetOnce.AlreadySetException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cache.recycler.PageCacheRecycler;
|
||||
import org.elasticsearch.client.Client;
|
||||
|
@ -43,8 +44,8 @@ import org.elasticsearch.env.NodeEnvironment;
|
|||
import org.elasticsearch.env.ShardLock;
|
||||
import org.elasticsearch.index.analysis.AnalysisRegistry;
|
||||
import org.elasticsearch.index.cache.query.QueryCache;
|
||||
import org.elasticsearch.index.cache.query.index.IndexQueryCache;
|
||||
import org.elasticsearch.index.cache.query.none.NoneQueryCache;
|
||||
import org.elasticsearch.index.cache.query.IndexQueryCache;
|
||||
import org.elasticsearch.index.cache.query.DisabledQueryCache;
|
||||
import org.elasticsearch.index.engine.Engine;
|
||||
import org.elasticsearch.index.engine.EngineException;
|
||||
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
|
||||
|
@ -320,9 +321,8 @@ public class IndexModuleTests extends ESTestCase {
|
|||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.addIndexOperationListener(null)).getMessage());
|
||||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.addSimilarity(null, null)).getMessage());
|
||||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.setSearcherWrapper(null)).getMessage());
|
||||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.forceQueryCacheType("foo")).getMessage());
|
||||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.forceQueryCacheProvider(null)).getMessage());
|
||||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.addIndexStore("foo", null)).getMessage());
|
||||
assertEquals(msg, expectThrows(IllegalStateException.class, () -> module.registerQueryCache("foo", null)).getMessage());
|
||||
}
|
||||
|
||||
public void testSetupUnknownSimilarity() throws IOException {
|
||||
|
@ -355,47 +355,13 @@ public class IndexModuleTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testCannotRegisterProvidedImplementations() {
|
||||
public void testForceCustomQueryCache() throws IOException {
|
||||
Settings indexSettings = Settings.builder()
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexModule module = new IndexModule(IndexSettingsModule.newIndexSettings("foo", indexSettings), null, new AnalysisRegistry(null, environment));
|
||||
try {
|
||||
module.registerQueryCache("index", IndexQueryCache::new);
|
||||
fail("only once");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(e.getMessage(), "Can't register the same [query_cache] more than once for [index]");
|
||||
}
|
||||
|
||||
try {
|
||||
module.registerQueryCache("none", (settings, x) -> new NoneQueryCache(settings));
|
||||
fail("only once");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(e.getMessage(), "Can't register the same [query_cache] more than once for [none]");
|
||||
}
|
||||
|
||||
try {
|
||||
module.registerQueryCache("index", null);
|
||||
fail("must not be null");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(e.getMessage(), "provider must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
public void testRegisterCustomQueryCache() throws IOException {
|
||||
Settings indexSettings = Settings.builder()
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), "custom")
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexModule module = new IndexModule(IndexSettingsModule.newIndexSettings("foo", indexSettings), null, new AnalysisRegistry(null, environment));
|
||||
module.registerQueryCache("custom", (a, b) -> new CustomQueryCache());
|
||||
try {
|
||||
module.registerQueryCache("custom", (a, b) -> new CustomQueryCache());
|
||||
fail("only once");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(e.getMessage(), "Can't register the same [query_cache] more than once for [custom]");
|
||||
}
|
||||
|
||||
module.forceQueryCacheProvider((a, b) -> new CustomQueryCache());
|
||||
expectThrows(AlreadySetException.class, () -> module.forceQueryCacheProvider((a, b) -> new CustomQueryCache()));
|
||||
IndexService indexService = module.newIndexService(nodeEnvironment, deleter, nodeServicesProvider, indicesQueryCache, mapperRegistry,
|
||||
new IndicesFieldDataCache(settings, listener));
|
||||
assertTrue(indexService.cache().query() instanceof CustomQueryCache);
|
||||
|
@ -413,17 +379,16 @@ public class IndexModuleTests extends ESTestCase {
|
|||
indexService.close("simon says", false);
|
||||
}
|
||||
|
||||
public void testForceCacheType() throws IOException {
|
||||
public void testDisableQueryCacheHasPrecedenceOverForceQueryCache() throws IOException {
|
||||
Settings indexSettings = Settings.builder()
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), "none")
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING.getKey(), false)
|
||||
.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir().toString())
|
||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build();
|
||||
IndexModule module = new IndexModule(IndexSettingsModule.newIndexSettings("foo", indexSettings), null, new AnalysisRegistry(null, environment));
|
||||
module.forceQueryCacheType("custom");
|
||||
module.registerQueryCache("custom", (a, b) -> new CustomQueryCache());
|
||||
module.forceQueryCacheProvider((a, b) -> new CustomQueryCache());
|
||||
IndexService indexService = module.newIndexService(nodeEnvironment, deleter, nodeServicesProvider, indicesQueryCache, mapperRegistry,
|
||||
new IndicesFieldDataCache(settings, listener));
|
||||
assertTrue(indexService.cache().query() instanceof CustomQueryCache);
|
||||
assertTrue(indexService.cache().query() instanceof DisabledQueryCache);
|
||||
indexService.close("simon says", false);
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public class IndexStatsIT extends ESIntegTestCase {
|
|||
public Settings indexSettings() {
|
||||
return Settings.builder().put(super.indexSettings())
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_EVERYTHING_SETTING.getKey(), true)
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), IndexModule.INDEX_QUERY_CACHE)
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING.getKey(), true)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ public class ChildQuerySearchIT extends ESIntegTestCase {
|
|||
public Settings indexSettings() {
|
||||
return Settings.builder().put(super.indexSettings())
|
||||
// aggressive filter caching so that we can assert on the filter cache size
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), IndexModule.INDEX_QUERY_CACHE)
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING.getKey(), true)
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_EVERYTHING_SETTING.getKey(), true)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -16,3 +16,10 @@ the cluster:
|
|||
Controls the memory size for the filter cache , defaults to `10%`. Accepts
|
||||
either a percentage value, like `5%`, or an exact value, like `512mb`.
|
||||
|
||||
The following setting is an _index_ setting that can be configured on a
|
||||
per-index basis:
|
||||
|
||||
`index.queries.cache.enabled`::
|
||||
|
||||
Controls whether to enable query caching. Accepts `true` (default) or
|
||||
`false`.
|
||||
|
|
|
@ -53,7 +53,7 @@ public class ScriptQuerySearchTests extends ESIntegTestCase {
|
|||
public Settings indexSettings() {
|
||||
return Settings.builder().put(super.indexSettings())
|
||||
// aggressive filter caching so that we can assert on the number of iterations of the script filters
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), IndexModule.INDEX_QUERY_CACHE)
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING.getKey(), true)
|
||||
.put(IndexModule.INDEX_QUERY_CACHE_EVERYTHING_SETTING.getKey(), true)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -399,7 +399,7 @@ public abstract class ESIntegTestCase extends ESTestCase {
|
|||
// always default delayed allocation to 0 to make sure we have tests are not delayed
|
||||
randomSettingsBuilder.put(UnassignedInfo.INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING.getKey(), 0);
|
||||
if (randomBoolean()) {
|
||||
randomSettingsBuilder.put(IndexModule.INDEX_QUERY_CACHE_TYPE_SETTING.getKey(), randomBoolean() ? IndexModule.INDEX_QUERY_CACHE : IndexModule.NONE_QUERY_CACHE);
|
||||
randomSettingsBuilder.put(IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING.getKey(), randomBoolean());
|
||||
}
|
||||
|
||||
if (randomBoolean()) {
|
||||
|
|
Loading…
Reference in New Issue