es filter过滤的bitset机制和caching机制

document存储数据为:

PUT /forum/article/_bulk
{ "index": { "_id": 1 }}
{ "articleID" : "XHDK-A-1293-#fJ3", "userID" : 1, "hidden": false, "postDate": "2017-01-01" }
{ "index": { "_id": 2 }}
{ "articleID" : "KDKE-B-9947-#kL5", "userID" : 1, "hidden": false, "postDate": "2017-01-02" }
{ "index": { "_id": 3 }}
{ "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-01-01" }
{ "index": { "_id": 4 }}
{ "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-01-02" }

查询语句(获取userid==1 && postDate==2017-01-01的document 并且articleID包含XHDK):

GET /forum/article/_search
{
  "query": {
    "bool": {
      "filter": [
        { "term":  { "hidden": "false"}},
        { "term": { "postDate": "2017-01-01" }} ,
{ "match": { "articleID":   "XHDK"}}
      ]
    }
  }
}

此语句查询过程,涉及到caching和bitset部分。

bitset机制

(1) 在倒排索引中查找字符串,获取documnet list。

(2)位每个在倒排索引中搜索到的结果,构建一个bitset。0代表不匹配,1代表匹配,使用bitset这种数据结构可以节省内存空间,提升性能。

"term":  { "hidden": "false"}------>[1,1,1,0]
"term": { "postDate": "2017-01-01" }----> [1,0,1,0]
"match": { "articleID":   "XHDK"}------> [1,0,0,0]

(3)遍历每个过滤条件对应的bitset,优先从最稀疏的开始搜索,查找所有满足所有条件的document

最稀疏的应该是"match": { "articleID":   "XHDK"}------> [1,0,0,0]。这样可以尽可能多的过滤掉documnet。
再过滤"term": { "postDate": "2017-01-01" }----> [1,0,1,0]
遍历完后bitset之后,找到所有匹配的document。[1,0,0,0],也就是document==1一个。

caching机制

(1)跟踪query,在最近256个query中超过一定次数的过滤条件,缓存其bitset。对于小segment(<1000,或<3%),不缓存bitset。

使用缓存,可以不用重新扫描倒排索引,不用反复生成bitset,可以大幅度提升性能。

为什么小的segment不进行缓存:segment数据量很小,此时哪怕是扫描也很快;segment会在后台自动合并,小segment很快就会跟其他小segment合并成大segment,此时就缓存也没有什么意义,segment很快就消失了。

(2)filter大部分情况下来说,在query之前执行,先尽量过滤掉尽可能多的数据

query:是会计算doc对搜索条件的relevance score,还会根据这个score去排序
filter:只是简单过滤出想要的数据,不计算relevance score,也不排序

(3)如果document有新增或修改,那么cached bitset会被自动更新

(4)以后只要是有相同的filter条件的,会直接来使用这个过滤条件对应的cached bitset

参考文档:https://www.jianshu.com/p/83e4771f697e

原文地址:https://www.cnblogs.com/parent-absent-son/p/11064819.html