filter执行原理
场景
举个例子,假设有个字段是date类型的,在倒排索引中:
word | document1 | document2 | document3 |
---|---|---|---|
2017-01-01 | √ | √ | |
2017-02-02 | √ | √ | |
2017-03-03 | √ | √ | √ |
在倒排索引中查找搜索串,获取document list
这时候一个filter查询:2017-02-02,在倒排索引里面找,对应的document list是doc2,doc3
为每个在倒排索引中搜索到的结果构建一个bitset
这点非常重要, 使用找到的document list构建一个bitset,一个二进制数组,数组每个元素都是0或1,用来标识一个doc对一个filter条件是否匹配,如果匹配就是1,不匹配就是0.
上面的例子中,构建的bitset就是[0,1,1]
尽可能用简单的数据结构去实现复杂的功能,可以节省内存空间,提升性能
遍历每个过滤条件对应的bitset,优先从最稀疏的开始搜索,查找满足条件的所有document
在一个search请求中,可以发出多个filter条件(这个后面再具体说),每个filter会对应一个bitset
遍历每个filter条件对应的bitset,先从最稀疏的开始遍历.
怎么算稀疏呢?
[0,0,0,1,0,0] – 比较稀疏
[0,1,0,1,0,1]
先遍历比较稀疏的bitset,可以过滤掉尽可能多的数据
比如现在有个请求 filter: postDate=2017-01,userID=1,然后构建的两个bitset分别是:
[0,0,1,==1==,0,0]
[0,1,0,==1==,0,1]
遍历玩两个bitset之后,找到匹配所有条件的document,就是第4个,这个时候就可以将符合结果document返回给客户端了
caching bitset 跟踪query
对于在最近的256个query中超过一定次数的过滤条件,缓存其bitset.
对于小segment(<1000或<3%)不缓存
举个例子,在最近的256次查询中,postDate=2017-02-02这个条件出现超过了一定的次数(不固定), 就会自动缓存这个filter对应的bitset
filter对于小的segment中获取到的结果可以不缓存, segment中记录数小于1000的和segment大小小于index总大小的3%的
因为segment数据量很小的时候,扫描是很快的,而且我们之前有说过,segment会在后台自动合并的,小的segment很快会和其他小的segment合并,此时缓存也就没有什么意义了
大部分情况下 filter会在query之前执行
filter先执行可以先过滤掉一部分数据,之前说过query是会计算相关度分数,然后去排序的,而filter是不计算分数,也不排序,所以先执行filter过滤掉尽可能多的数据
如果document有新增或修改,那么cached bitset会被自动更新
举个例子,之前有个filter 过滤条件是postDate=2017-02-02,然后他的bitset是[0,0,0,1]
这个时候如果新增了一条document进来 postDate也是 2017-02-02,id是5, 那么这个bitset会自动更新为[0,0,0,1,1]
同理,如果id = 1的document的postDate更新为2017-02-02 那么bitset也会更新为[1,0,0,1,1]