1. 节点查询缓存(Node Query Cache)
官方文档简介
查询缓存负责缓存查询的结果。每个节点有一个查询缓存,由所有分片共享。缓存执行LRU回收策略:当缓存满时,将回收最近最少使用的数据,为新数据让路。无法查看正在缓存的内容。
查询缓存只缓存在filter
上下文中使用的查询。
详细介绍
缓存数据结构
缓存分为两个级别,分别为Query
和Segment
,所以使用的数据结构是一个Map<Query, Map<Segment, DocIdSet>>
,DocIdSet
则使用的是BitSet
参数说明
indices.queries.cache.size
: 控制Filter
缓存的内存大小,默认为10%
。接受百分比值(如5%
)或精确值(如512mb
)。
indices.queries.cache.count
: 在官方文档并没有写,这是一个节点级别的配置,可以在elasticsearch.yml
中配置,控制缓存的总数量。如果缓存文档数量达到了该值,即使缓存大小还没有达到上限,也没有办法再利用了。值得注意的是,如果一个查询在本节点涉及到多个Segment,那么实际的cache_size将会是本值与Segment数量的乘积。
indices.queries.cache.all_segments
: 用于是否在所有Segment
上启用缓存,默认是false
,不会对文档数小于100000
并且小于整个索引大小的3%
的Segment进行缓存。
index.queries.cache.enabled
: 控制是否启用查询缓存。接受true
(默认值)或false
。
可以被缓存的查询语句要求
-
对于
TermQuery
、MatchAllDocsQuery
等这种查询都不被缓存。当BooleanQuey
的字节点为空时不会被缓存,当Dis Max Query
的Disjuncts
为空时不会被缓存。 -
对于历史查询次数有要求,对于消耗高昂的
Query
只需要2
次就加入缓存,其他的默认是5
次,对于BooleanQuery
和DisjunctionMaxQuery
次数为4
次。
什么样的Segment会被缓存
Segment
中文档数大于100000
或者大于整个所以大小的3%
。如果想要索引所有段,可以设置indices.queries.cache.all_segments
新索引的文档,缓存会失效或者重新构建吗
缓存不会失效,而是通过判断文档是否符合Query
的条件,如果符合条件的话则会将文档加入到BitSet
中。
案例
查看ES查询缓冲情况
curl 'http://es.zjw.cn:9200/_stats/query_cache?pretty&human'
返回结果query_cache部分
"query_cache": {
"memory_size": "2.5gb",
"memory_size_in_bytes": 2690321531,
"total_count": 83881663356,
"hit_count": 37834074368,
"miss_count": 46047588988,
"cache_size": 118427,
"cache_count": 42784311,
"evictions": 42665884
}
从当前的query_cache
看,evictions
是cache_size
的360倍,说明cache_size
过小,导致缓存倍频繁淘汰,导致缓存命中比例较小,可以适当调大indices.queries.cache.size
大小和indices.queries.cache.count
。
2. 字段数据缓存(Field data Cache)
主要用于sort
以及aggs
的字段。这会把字段的值加载到内存中,以便于快速访问。field data cache
的构建非常昂贵,因此最好能分配足够的内存以保障它能长时间处于被加载的状态。或者在创建索引时预见到某字段会被用于排序和聚合,而设置文档值,避免使用field data cache
。
一定要注意数据建模,对于不合理的字段启用field data cache
代价非常大,而且性能特别差!
indices.fielddata.cache.size
: 用来控制缓存的大小,支持两种格式,一种是百分数(代表占节点heap
的百分比),另一种是精确值(如10gb
),默认是无限。
3. 分片请求缓存(Shard Request Cache)
Shard
级别的缓存。默认的主要用于缓存size=0
的请求(aggs
和suggestions
,还有就是hits.total
)。
每当分片索引refresh
的时候,如果数据发生了实际变化,那么缓存就会自动失效。所以refresh
时间越长,那么缓存的时间也就越长。缓存采用的也是LRU
淘汰策略。
缓存是以请求的
JSON
为Key
来进行存储的,那么也就是说,当同样含义的不同形式的请求将无法识别缓存。
索引级别禁用缓存
index.requests.cache.enable
: 这个参数用来控制是否启用分片级别的缓存,默认是false
请求时禁用缓存
通过url
传参方式request_cache=false
主要的缓存配置
indices.requests.cache.size
用来控制缓存在heap
中的大小,默认是1%
。
4. 索引缓存(Indexing Buffer)
用于缓存新索引的数据,用于缓存新索引的数据,当空间填满之后,会将数据写到磁盘上成为一个新的段。它被划分为节点上的所有分片。以下设置为静态设置,必须在集群中的每个数据节点上配置:
indices.memory.index_buffer_size
: 接受百分比或字节大小值。默认值为10%
,这意味着分配给节点的堆总量的10%
将被用作跨所有分片共享的索引缓冲区大小。
indices.memory.min_index_buffer_size
: 如果index_buffer_size
被指定为一个百分比,那么这个设置可以用来指定一个绝对的最小值。默认为48mb
。
indices.memory.max_index_buffer_size
: 如果index_buffer_size
被指定为一个百分比,那么这个设置可以用来指定一个绝对最大值。默认为无限。