elasticsearch中如何⾼效的使⽤filter
elasticsearch⾥⾯有BOOL 、AND、OR、NOT ,这⼏个看起来很相似,都有什么区别呢?什么时候⽤bool?什么时候⽤AND filter呢?
事实上,bool filter和AND 、OR、NOT filter 是完全不同,在查询性能上⾯的影响是⾮常⼤的。
⾸先咱们需要了解的是filter⾥⾯都是怎么⼯作的,其中核⼼的⼀个东西叫,可以理解为⼀个很⼤的bit数组,数组⾥⾯的每个元素有2个状态:0和1(bloom filter知道么?),⽽filter⼤家都知道,只处理⽂档是否匹配与否,不涉及⽂档评分操作。如果⼀个⽂档和filter查询匹配,那么其对应的bit位就设置为1,匹配不上则设置为0。
filter过滤对象数组es在执⾏filter查询过滤的时候,会打开lucene的每个segment段⽂件,然后去判断⾥⾯的⽂档符合该filter与否,这个匹配的结果我们就可以⽤bitset来存储起来,下次同样的filter查询过来,我们就直接使⽤内存⾥⾯的bitset来进⾏判断就⾏了,⽽不需要再打开lucene的segment⽂件了,避免了io的操作,这样就可以⼤⼤提⾼查询处理的速度,这也是为什么filter这么⾼效的原因。
因为lucene的segment段⽂件是不变的,lucene会产⽣新段,但是旧段是不变的,所以bitset是重复利⽤的,根据不同的filter条件和不同的段,会产⽣相应的bitset,另外不同的查询可能会涉及到多个bitset的做交集,计算机对这种bit位处理过程是⾮常拿⼿的,速度很快。
另外,如果filter的结果如果是空的,那么⾥⾯的bitset位都是0,es以后在处理该filter的时候,会把该bitset整个忽略掉,提⾼性能。
前⾯说完了基础内容,咱们再看看bool filter和AND filter这些的区别吧
bool filter会使⽤到前⾯提到过的bitset数据结构(bitset派),⽽AND \OR\ NOTfilter则不能利⽤到bitset(non-bitset派),为什么呢?AND、OR、NOT filter是doc by doc的逐个⽂档的处理,es逐个加载⽂档⾥⾯的字段内容,然后检查字段的内容是否满⾜查询条件,不满⾜的⽂档就排除在结果集之外,依次迭代进⾏,直到过完⼀遍所有的⽂档,这中间的过程⽤不到前⾯提到过的bitset,也就不能重复利⽤缓存资源
如果你有多个filter条件,即⼀个AND、OR、NOT⾥⾯包含多个filter过滤条件(⽀持数组的⽅式),那么处理的逻辑就是每个filter会将依次将⽣成的结果集传到下⼀个filter,理论上处理的⽂档数会越来越少,因为只会过滤减少,不会增加,这样依次过滤,所以⼀般限制条件⽐较苛刻的可以放前⾯执⾏,这样后⾯的filter需要处理的⽂档数就会很⼩,这样可以⼤⼤提⾼整体处理的速度,另外除了数量上的考虑外,还需要考虑filter的效率问题,⼀些filter执⾏效率很低,如Geo filter(⼤量计算)或者script based filter(动态脚本),建议将这些性能开销⽐较⼤的查询放最后执⾏来提⾼整体的处理速度。
好了,现在应该有这么⼀个概念了,AND、OR、NOT是⽂档by⽂档,依次处理,如果你的结果集很
⼤,即⼀个很宽松的查询,命中很多,那么你使⽤AND、OR、NOT filter是不合适的,但是有些filter是必须⽂档by⽂档处理的,如下⾯的这⼏个filter:
Geo* filters
Scripts
Numeric_range
所以除了上⾯那⼏个没有办法的,其它的filter应该⼀律使⽤bool filter来提⾼查询性能。
如果你的查询⾥⾯需要同时使⽤到bitset和non-bitset类型的filter,则可以组合起来使⽤bool filter和AND\OR\NOT filter,
前⾯说了,AND 是结果集依次向后传递,所以我们把性能⽐较好的放前⾯,non-bitset放AND的filter的后⾯,如下⾯⼀个包含多个filter类型的复杂的filter
{
"and" : [
{
"bool" : {
"must" : [
{"term" : {}},
{"range" : {}},
{"term" : {}}
]
}
},
{
"or" : [
{"custom_script" : {}},
{"geo_distance" : {}}
]
}
]
}
and 在最外层做wrapper,第⼀个filter是⼀个bool filter,⾥⾯有3个must的⼦filter,处理完了之后,得到⽂档结果集,然后再执⾏⼀个or的⼦filter,OR⾥⾯两个查询会分别进⾏,最终的⽂档结果集就是我们的搜索结果了。
总之,filter使⽤的时候,⼀定要优先使⽤bitset流,然后还要考虑filter顺序和组合的问题Geo, Script or Numeric_range filter: 使⽤ And/Or/Not Filters
所有其它的: 使⽤ Bool Filter
掌握了以上这些,就不难写出⾼性能的查询了。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论