Elasticsearch进阶笔记第二篇

436 阅读5分钟

Elasticsearch高手进阶篇(3)

结构化搜索_filter执行原理深度剖析(bitset机制与caching机制)

(1)在倒排索引中查找搜索串,获取document list

date来举例

worddoc1doc2doc3
2017-01-01**
2017-02-02**
2017-03-03***

filter:2017-02-02

到倒排索引中一找,发现2017-02-02对应的document list是doc2,doc3

(2)为每个在倒排索引中搜索到的结果,构建一个bitset,[0, 0, 0, 1, 0, 1]

非常重要

使用找到的doc list,构建一个bitset,就是一个二进制的数组,数组每个元素都是0或1,用来标识一个doc对一个filter条件是否匹配,如果匹配就是1,不匹配就是0

[0, 1, 1]

doc1:不匹配这个filter的 doc2和do3:是匹配这个filter的

尽可能用简单的数据结构去实现复杂的功能,可以节省内存空间,提升性能

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

  • 后面会讲解,一次性其实可以在一个search请求中,发出多个filter条件,每个filter条件都会对应一个bitset,遍历每个filter条件对应的bitset,先从最稀疏的开始遍历

[0, 0, 0, 1, 0, 0]:比较稀疏 [0, 1, 0, 1, 0, 1]

先遍历比较稀疏的bitset,就可以先过滤掉尽可能多的数据

遍历所有的bitset,找到匹配所有filter条件的doc

请求:filter,postDate=2017-01-01,userID=1

postDate: [0, 0, 1, 1, 0, 0] userID: [0, 1, 0, 1, 0, 1]

遍历完两个bitset之后,找到的匹配所有条件的doc,就是doc4

就可以将document作为结果返回给client了

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

  • 比如postDate=2017-01-01,[0, 0, 1, 1, 0, 0],可以缓存在内存中,这样下次如果再有这个条件过来的时候,就不用重新扫描倒排索引,反复生成bitset,可以大幅度提升性能。
  • 在最近的256个filter中,有某个filter超过了一定的次数,次数不固定,就会自动缓存这个filter对应的bitset

segment(上半季),filter针对小segment获取到的结果,可以不缓存,segment记录数<1000,或者segment大小<index总大小的3%

  • segment比较小的情况下,不进行缓存的原因

    • segment数据量很小,此时哪怕是扫描也很快;segment会在后台自动合并,小segment很快就会跟其他小segment合并成大segment,此时就缓存也没有什么意义,segment很快就消失了
    • 针对一个小segment的bitset,[0, 0, 1, 0]
  • filter比query的好处就在于会caching,但是之前不知道caching的是什么东西,实际上并不是一个filter返回的完整的doc list数据结果。而是filter bitset缓存起来。下次不用扫描倒排索引了。

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

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

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

postDate=2017-01-01,[0, 0, 1, 0]

  • document,id=5,postDate=2017-01-01,会自动更新到postDate=2017-01-01这个filter的bitset中,全自动,缓存会自动更新。postDate=2017-01-01的bitset,[0, 0, 1, 0, 1]
  • document,id=1,postDate=2016-12-30,修改为postDate-2017-01-01,此时也会自动更新bitset,[1, 0, 1, 0, 1]

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

Elasticsearch高手进阶篇(4)

结构化搜索_在案例中实战基于bool组合多个filter条件来搜索数据

实例1

  • 搜索发帖日期为2017-01-01,或者帖子ID为XHDK-A-1293-#fJ3的帖子,同时要求帖子的发帖日期绝对不为2017-01-02
 select * from forum.article where (post_date='2017-01-01' or article_id='XHDK-A-1293-#fJ3') and post_date!='2017-01-02'

使用ES的语法如下

 GET /waws/article/_search
 {
   "query": {
     "constant_score": {
       "filter": {
         "bool": {
           "should": [
             {
               "term": {
                 "articleID.keyword": "XHDK-A-1293-#fJ3"
               }
             },
             {
               "term": {
                 "post_date": "2017-01-01"
               }
             }
           ],
           "must_not": {
             "term": {
               "post_date": "2017-01-02"
             }
           }
         }
       }
     }
   }
 }
 
 {
   "took": 3,
   "timed_out": false,
   "_shards": {
     "total": 5,
     "successful": 5,
     "failed": 0
   },
   "hits": {
     "total": 1,
     "max_score": 1,
     "hits": [
       {
         "_index": "waws",
         "_type": "article",
         "_id": "1",
         "_score": 1,
         "_source": {
           "articleID": "XHDK-A-1293-#fJ3",
           "userID": 1,
           "hidden": false,
           "postDate": "2017-01-01"
         }
       }
     ]
   }
 }

must,should,must_not,filter:必须匹配,可以匹配其中任意一个即可,必须不匹配

实例2

  • 搜索帖子ID为XHDK-A-1293-#fJ3,或者是帖子ID为JODL-X-1937-#pV7而且发帖日期为2017-01-01的帖子
 select * from forum.article where article_id='XHDK-A-1293-#fJ3' or (article_id='JODL-X-1937-#pV7' and post_date='2017-01-01')

使用ES的语法如下

 GET /waws/article/_search 
 {
   "query": {
     "constant_score": {
       "filter": {
         "bool": {
           "should": [
             {
               "term": {
                 "articleID.keyword": "XHDK-A-1293-#fJ3"
               }
             },
             {
               "bool": {
                 "must": [
                   {
                     "term":{
                       "articleID.keyword": "JODL-X-1937-#pV7"
                     }
                   },
                   {
                     "term": {
                       "postDate": "2017-01-01"
                     }
                   }
                 ]
               }
             }
           ]
         }
       }
     }
   }
 }
 ​
 {
   "took": 2,
   "timed_out": false,
   "_shards": {
     "total": 5,
     "successful": 5,
     "failed": 0
   },
   "hits": {
     "total": 2,
     "max_score": 1,
     "hits": [
       {
         "_index": "waws",
         "_type": "article",
         "_id": "1",
         "_score": 1,
         "_source": {
           "articleID": "XHDK-A-1293-#fJ3",
           "userID": 1,
           "hidden": false,
           "postDate": "2017-01-01"
         }
       },
       {
         "_index": "waws",
         "_type": "article",
         "_id": "3",
         "_score": 1,
         "_source": {
           "articleID": "JODL-X-1937-#pV7",
           "userID": 2,
           "hidden": false,
           "postDate": "2017-01-01"
         }
       }
     ]
   }
 }

梳理学到的知识点

  • bool:must,must_not,should,组合多个过滤条件
  • bool可以嵌套
  • 相当于SQL中的多个and条件:当你把搜索语法学好了以后,基本可以实现部分常用的sql语法对应的功能