elasticsearch four search type

elasticsearch 四种搜素类型

  1. ES 四种搜索类型

    1
    2
    3
    4
    5
    ES 在查询时,可以指定搜索类型有四种:
    * QUERY_THEN_FETCH
    * QUERY_AND_FEATCH
    * DFS_QUERY_THEN_FEATCH
    * DFS_QUERY_AND_FEATCH
  2. 理解分布式搜索

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    分布式搜索背景介绍:
    ES 天生就是为分布式而生,但分布式有分布式的缺点,比如: 要搜索某个单词,但是数据却分别在5个分片(Shard)上,这5个分片可能在5台主机上面.因为全文搜索天生就要排序(照匹配度进行排名),但数据却在5个分片上,如何得到最后正确的排序呢?ES是这样做的,大概分三步:
    1.ES 客户端将会同时向5个分片发起搜索请求
    2.这5个分片基于本分片的内容独立完成搜索,然后将符合条件的结果全部返回
    3.客户端将返回的结果进行重新排序和排名,最后返回给用户.也就是说,ES的一次搜索,是一次scatter/gather过程(这个跟mapreduce也很类似)

    然而这其中有两个问题:
    1.数量问题
    比如,用户需要搜索"衣服",要求返回符合条件的前10条.但在5个分片中,可能都存储着衣服相关的数据.所以ES会向这5个分片都发出查询请求,并且要求每个分片都返回符合条件的10条记录.当ES得到返回的结果后,进行整体排序,然后取最符合条件的前10条返给用户.这种情况,ES中5个shard最多会收到10*5=50条记录,这样返回给用户的结果数量会多于用户请求的数量.
    2.排名问题
    上面说的搜索,每个分片计算符合条件的前10条数据都是基于自己分片的数据进行打分计算的.计算分值使用的词频和文档频率等信息都是基于自己分片的数据进行的,而ES进行整体排名是基于每个分片计算后的分值进行排序的(相当于打分依据就不一样,最终对这些数据统一排名的时候就不准确了),这就可能会导致排名不准确的问题.如果我们想更精确的控制排序,应该先将计算排序和排名相关的信息(词频和文档频率等打分依据)从5个分片收集上来,进行统一计算,然后使用整体的词频和文档频率为每个分片中的数据进行打分,这样打分依据就一样了.
    1
    2
    3
    再举个例子解释一下[排名问题]:
    假设某学校有一班和二班两个班级.期末考试之后,学校要给全校前十名学员发奖金.但是一班和二班考试的时候使用的不是一套试卷.一班使用的是A卷[ A 卷偏容易];二班使用的是B卷[ B 卷偏难].结果就是一班的最高分是100分,最低分是80分.二班的最高分是70分,最低分是30分.这样全校前十名就都是一班的学员了.这显然是不合理的.因为一班和二班的试卷难易程度不一样,也就是打分依据不一样,所以不能放在一块排名.
    如果想要保证排名准确的话,需要保证一班和二班使用的试卷内容一样.可以这样做,把A卷和B卷的内容组合到一块,作为C卷.一班和二班考试都使用C卷,这样他们的打分依据就一样了,最终再根据所有学员的成绩排名求前十名就准确合理了。
  3. 四种搜索类型介绍

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    * query and fetch
     向索引的所有分片(shard)都发出查询请求,各分片返回的时候把元素文档(document)和计算后的排名信息一起返回.
    这种搜索方式是最快的.因为相比下面的几种搜索方式,这种查询方法只需要去shard查询一次.但是各个shard返回的结果的数量之和可能是用户要求的size的n倍.
     优点:只需要查询一次
     缺点:返回的数据量不准确,可能返回(N*分片数量)的数据并且数据排名也不准确

    * query then fetch(ES默认的搜索方式)
     如果你搜索时,没有指定搜索方式,就是使用的这种搜索方式.这种搜索方式.大概分两个步骤:
     第一步,先向所有的shard发出请求,各分片只返回文档id(注意,不包括文档document)和排名相关的信息(也就是文档对应的分值),然后按照各分片返回的文档的分数进行重新排序和排名,取前size个文档
     第二步,根据文档id去相关的shard取document.这种方式返回的document数量与用户要求的大小是相等的
     优点:返回的数据量是准确的
     缺点:性能一般,并且数据排名不准确

    * DFS query and fetch
     这种方式比第一种方式多了一个DFS步骤,有这一步,可以更精确控制搜索打分和排名.也就是在进行查询之前,先对所有分片发送请求,把所有分片中的词频和文档频率等打分依据全部汇总到一块,再执行后面的操作.
     优点:数据排名准确
     缺点:性能一般,返回的数据量不准确,可能返回(N*分片数量)的数据

    * DFS query then fetch
     比第2种方式多了一个DFS步骤,也就是在进行查询之前,先对所有分片发送请求,把所有分片中的词频和文档频率等打分依据全部汇总到一块,再执行后面的操作.
    优点:返回的数据量是准确的,数据排名准确
     缺点:性能最差(这个最差只是表示在这四种查询方式中性能最慢,也不至于不能忍受,如果对查询性能要求不是非常高,而对查询准确度要求比较高的时候可以考虑这个)

    其他: DFS 是一个什么样的过程?
    DFS其实就是在进行真正的查询之前,先把各个分片的词频率和文档频率收集一下,然后进行词搜索的时候,各分片依据全局的词频率和文档频率进行搜索和排名.显然如果使用DFS_QUERY_THEN_FETCH这种查询方式,效率是最低的,因为一个搜索,可能要请求3次分片.但使用DFS方法,搜索精度是最高的.

    总结一下:
    1.从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的
    2.从搜索的准确度来说,DFS要比非DFS的准确度更高