前面说起了字段过滤缓存,那么与之相反的清楚缓存策略
单一索引缓存,多索引缓存和所有缓存的清理正则表达式
1.清空所有缓存
curl localhost:9200/_cache/clear?pretty
{
"_shards" : {
"total" : 72,
"successful" : 72,
"failed" : 0
}
}数据库
2.清除单一索引缓存
curl localhost:9200/index/_cache/clear?pretty
{
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
}
}json
3.清除多索引缓存
curl localhost:9200/index1,index2,index3/_cache/clear?pretty
{
"_shards" : {
"total" : 12,
"successful" : 12,
"failed" : 0
}
}
固然了清楚缓存时也能够添加参数使之清楚对用的缓存并不是全部的
filter:此类缓存能够设置filter参数为true来清理,相反的不须要清楚此类缓存那么能够设置参数为false来保留此类缓存
field_data:此类缓存能够设置filter参数为true来清理,相反的不须要清楚此类缓存那么能够设置参数为false来保留此类缓存
bloom:此类缓存能够设置filter参数为true来清理(若是某种倒排索引格式中引用了bloom filter则可能使用此类缓存),相反的不须要清楚此类缓存那么能够设置参数为false来保留此类缓存
fields:清楚字段相关的缓存,能够为单个或者多个字段,多个字段的时候用逗号隔开(英文)缓存
上述参数使用格式(可使用一个或者多个参数)
curl localhost:9200/index/_cache/clear?pretty&filter=false&field_data=true&bloom=false&fields=tag,name数据结构
Query Cache也称为Filter Cache,顾名思义它的做用就是对一个查询中包含的过滤器执行结果进行缓存。app
好比咱们经常使用的term,terms,range过滤器都会在知足某种条件后被缓存,注意,这里的bool过滤器是不会被缓存的,但bool过滤器包含的子query clause会被缓存,咱们能够用下面的命令来查询Query Cache的状况。dom
http://192.168.0.109:9200/_stats/query_cache?pretty&human
举个栗子,看下面的查询curl
{ "from": 0, "size": 5, "query": { "bool": { "filter": { "bool": { "must": [ { "term": { "productID": "JODL-X-1937-#pV7" } }, { "range": { "price": { "from": 20, "to": null, "include_lower": true, "include_upper": true } } } ] } } } } }
上面有两个过滤器一个Term过滤器用来过滤productID为“JODL-X-1937-#pV7” 的产品,一个range过滤器用来过滤价格在20以上的产品,在这个例子中这两个过滤器执行的结果会分别做为一个BitSet(位图)缓存,返回的查询结果则是这两个位图交集。elasticsearch
上面提到Filter Cache只会在知足某种条件下才会被缓存,至因而哪些条件这里就不介绍了,想了解的童鞋戳下面连接。函数
关于Filter执行流程及缓存原理 ,请参看此文:《Elasticsearch2.X Filter执行流程及缓存原理》
当一个查询发送到ES集群的某个节点上时,这个节点会把该查询扩散到其余节点并在相应分片上执行,咱们姑且把在分片上执行的结果叫“本地结果集“,这些本地结果集最终会聚集到最初请求到达的那个协调节点,这些“分片级”的结果集会合并成“全局”结果集返回给调用端。
Request Cache模块就是为了缓存这些“分片级”的本地结果集,可是目前只会缓存查询中参数size=0的请求,因此就不会缓存hits 而是缓存 hits.total,aggregations和suggestions
Request Cache是很是智能的,它可以保证和在近实时搜索中的非缓存查询结果一致。这句话读起来很难懂,简单解释下。
咱们都知道ES是一个“near real-time”(近实时)搜索引擎,为何是近实时搜索呢,那是由于当咱们向ES发送一个索引文档请求到这个文档变成Searchable(可搜索)默认的时间是1秒,咱们能够经过index.refresh_interval参数来设置刷新时间间隔,也就是说咱们在执行一个搜索请求时实际上数据是有延迟的。回到刚才的问题,刚才那句话其实指的就是:ES能保证在使用Request Cache的状况下的搜索结果和不使用Request Cache的近实时搜索结果相同,那ES是如何保证二者结果相同的呢?继续……
Request Cache缓存失效是自动的,当索引refresh时就会失效,也就是说在默认状况下Request Cache是每1秒钟失效一次(注意:分片在这段时间内确实有改变才会失效)。也就是说当一个文档被索引到该文档变成Searchable以前的这段时间内,不论是否有请求命中缓存该文档都不会被返回,正是是由于如此ES才能保证在使用Request Cache的状况下执行的搜索和在非缓存近实时搜索的结果一致。
若是咱们把索引刷新时间设置得越长那么缓存失效的时间越长,若是缓存被写满将采用LRU策略清除。固然咱们也能够手动设置参数indices.request.cache.expire指定失效时间,可是基本上咱们不必去这样作,由于缓存在每次索引refresh时都会自动失效。
下面的命令能够手动清除缓存
curl -XPOST 'localhost:9200/kimchy,elasticsearch/_cache/clear?request_cache=true'
在默认状况下Request Cache是关闭的,咱们须要手动开启
curl -XPUT localhost:9200/my_index/_settings -d' { "index.requests.cache.enable": true } '
开启缓存后,咱们须要在那些须要缓存的搜索请求上加上request_cache=true这个参数才能使咱们的查询请求被缓存,好比:
curl 'localhost:9200/my_index/_search?request_cache=true' -d' { "size": 0, "aggs": { "popular_colors": { "terms": { "field": "colors" } } } }'
注意1:上面的参数size:0很是重要必须强制指定才能被缓存,不然请求是不会缓存的。
注意2(重要):在使用script执行查询时必定要指定request_cache=false,由于脚本的执行结果是不肯定的(好比使用random函数或使用了当前时间做为参数),这种状况下应该避免使用缓存
对于Request Cache来讲,它的Cache Key就是整个查询的DSL语句,因此若是要命中缓存查询生成的DSL必定要同样,这里的同样是指DSL这个字符串同样。只要有一个字符或者子查询的顺序变化都不会命中缓存。
经过下面的参数咱们能够设置缓存的大小,默认状况下是JVM堆的1%大小,固然咱们也能够手动设置在elasticsearch.yml文件里
indices.requests.cache.size: 1%
Request Cache总结:
一谈到Fielddata咱们不得不提到doc_values,这二者的做用都是同样:可以让咱们在inverted index(倒排索引)的基础之上作aggregation、sort或者在查询中经过script访问doc属性,这里咱们不讨论doc_values,主要讲下Fielddata,doc values相关知识请戳:http://blog.csdn.net/chennanymy/article/details/52555055
想必你们都知道倒排索引这种结构,若是咱们仅仅依靠倒排是很难在查询中作到排序和统计的,由于它并非像关系型数据库那样采用“列式存储”,而是基于一个“词”到“文档”的倒排。
Fielddata是专门针对分词的字段在query-time(查询期间)的数据结构的缓存。当咱们第一次在一个分词的字段上执行聚合、排序或经过脚本访问的时候就会触发该字段Fielddata Cache的加载,这种缓存是“segment”级别的,当有新的segment打开时旧的缓存不会从新加载,而是直接把新的segement对应的Fielddata Cache加载到内存。
加载Fielddata Cache是一个很是昂贵的操做,一旦Fielddata被加载到内存,那么在该Fielddata Cache对应的Segement生命周期范围内都会驻留在内存中。也就是说当段合并时会触发合并后更大段的Fielddata Cache加载。
Fielddata会消耗大部分的JVM堆内存,特别是当加载“高基数”的分词字段时(那些分词后存在大量不一样词的字段),针对这种字段的聚合排序实际上是很是没有意义的,咱们更多的要去考虑是否能用not_analyzed代替(这样就可使用doc_values实现聚合、排序)。
默认状况下Fielddate Cache是默认开启的,咱们能够经过下面的设置来关闭,关闭后就没法对分词字段执行聚合、排序操做了。
PUT my_index { "mappings": { "my_type": { "properties": { "text": { "type": "string", "fielddata": { "format": "disabled" } } } } } }
在ES1.X里面除了string类型其余类型也是使用Fieldata的,在ES2.X中除了分词的String类型字段,其余类型都使用doc_values。
Fielddata的加载方式有3种:
1.lazy: 懒加载是默认的加载方式,当第一次使用时加载
2.eager:预加载模式是当一个新的索引段变成Searchable以前会被加载
3.eager_global_ordinals:全局序数预加载模式,这种方式能生成一份全局序数表,可下降内存使用。
以下设置为eager_global_ordinals
PUT my_index { "mappings": { "my_type": { "properties": { "text": { "type": "string", "fielddata": { "loading": "eager_global_ordinals" } } } } } }
Fielddata也可指定知足某些条件的term才被加载进内存
1.经过词频加载
PUT my_index { "mappings": { "my_type": { "properties": { "tag": { "type": "string", "fielddata": { "filter": { "frequency": { "min": 0.001, "max": 0.1, "min_segment_size": 500 } } } } } } } }
上面的设置表示词频在0.001到0.1之间的且段持有的文档数在500以上的term会被加载到内存。
2.经过正则表达式加载
PUT my_index { "mappings": { "my_type": { "properties": { "tweet": { "type": "string", "analyzer": "whitespace", "fielddata": { "filter": { "regex": { "pattern": "^#.*" } } } } } } } }
上面的设置表示只有知足pattern的词才会被加载到内存。
Fielddata Cache设置
1.indices.fielddata.cache.size:此参数设置缓存大小(默认是不限制)。可设置百分数如30%,或者数字12GB
2.indices.breaker.fielddata.limit:此参数设置Fielddata断路器限制大小(公式:预计算内存 + 现有内存 <= 断路器设置内存限制),默认是60%JVM堆内存,当查询尝试加载更多数据到内存时会抛异常(以此来阻止JVM OOM发生)
3.indices.breaker.fielddata.overhead:一个常数表示内存预估值系数,默认1.03,好比预计算加载100M数据,那么100*1.03=103M会用103M做为参数计算是否超过断路器设置的最大值。