ElasticSearch SearchType详解

一篇关于ElasticSearch SearchType的详情

 点击打开链接

学习了

SearchType详解

es在查询时,可以指定搜索类型为 
QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCHDFS_QUERY_AND_FEATCHSACN,COUNT都已不建议使用)。那么这4种搜索类型有什么区别?

elasticsearch java api中还有个default 

public static final SearchType DEFAULT = QUERY_THEN_FETCH; 

分布式搜索背景介绍:

ES天生就是为分布式而生,但分布式有分布式的缺点。比如要搜索某个单词,但是数据却分别在5个分片(Shard)上面,这5个分片可能在5台主机上面。因为全文搜索天生就要排序(按照匹配度进行排名),但数据却在5个分片上,如何得到最后正确的排序呢?ES是这样做的,大概分两步。

step1. ES客户端会将这个搜索词同时向5个分片发起搜索请求,这叫Scatter, 
step2. 这5个分片基于本Shard独立完成搜索,然后将符合条件的结果全部返回,这一步叫Gather。 
客户端将返回的结果进行重新排序和排名,最后返回给用户。也就是说,ES的一次搜索,是一次scatter/gather过程(这个跟mapreduce也很类似).

然而这其中有两个问题:

第一、数量问题。比如,用户需要搜索”双黄连”,要求返回最符合条件的前10条。但在5个分片中,可能都存储着双黄连相关的数据。所以ES会向这5个分片都发出查询请求,并且要求每个分片都返回符合条件的10条记录。当ES得到返回的结果后,进行整体排序,然后取最符合条件的前10条返给用户。这种情况,ES5个shard最多会收到10*5=50条记录,这样返回给用户的结果数量会多于用户请求的数量。

第二、排名问题。上面搜索,每个分片计算分值都是基于自己的分片数据进行计算的。计算分值使用的词频率和其他信息都是基于自己的分片进行的,而ES进行整体排名是基于每个分片计算后的分值进行排序的,这就可能会导致排名不准确的问题。如果我们想更精确的控制排序,应该先将计算排序和排名相关的信息(词频率等)从5个分片收集上来,进行统一计算,然后使用整体的词频率去每个分片进行查询。

这两个问题,估计ES也没有什么较好的解决方法,最终把选择的权利交给用户,方法就是在搜索的时候指定query type。 
1、query and fetch 
向索引的所有分片(shard)都发出查询请求,各分片返回的时候把元素文档(document)和计算后的排名信息一起返回。这种搜索方式是最快的。因为相比下面的几种搜索方式,这种查询方法只需要去shard查询一次。但是各个shard返回的结果的数量之和可能是用户要求的size的n倍。

2、query then fetch(默认的搜索方式) 
如果你搜索时,没有指定搜索方式,就是使用的这种搜索方式。这种搜索方式,大概分两个步骤,第一步,先向所有的shard发出请求,各分片只返回排序和排名相关的信息(注意,不包括文档document),然后按照各分片返回的分数进行重新排序和排名,取前size个文档。然后进行第二步,去相关的shard取document。这种方式返回的document可能是用户要求的size的n倍,此处勘误,这是原博客中的错误,经测试 query then fetch 方式返回的数量就是 查询是 setSize()的数量

3、DFS query and fetch 
这种方式比第一种方式多了一个初始化散发(initial scatter)步骤,有这一步,据说可以更精确控制搜索打分和排名。这种方式返回的document与用户要求的size是相等的。同样勘误 DFS query and fetch 返回结果的数量是 分片数*size

4、DFS query then fetch 
比第2种方式多了一个初始化散发(initial scatter)步骤。这种方式返回的document与用户要求的size是相等的。


结论:

QUERY_AND_FETCH 和 QUERY_AND_FETCH 的排序方式没有本质区别 都是各个分片取size片 统一排序,区别在于 QUERY_AND_FETCH 是将所有数据取回再进行排序 只访问一次索引 而QUERY_AND_FETCH 是先将所有数据的id和score取回 排序后取前size的id 再根据id到各个分片召回对应的文档 访问了两次索引
所以二者的排序结果一致,但这二者存在同一个缺陷 各个分片计分规则不同(各个分片的词频等会影响计分结果)相关性排序上会有些误差
而DFS_QUERY_AND_FETCH 和 DFS_QUERY_THEN_FETCH 是统一了计分规则 保证查到的数据是索引中最最相关的,但时效性较前二者有劣势

DSF是什么缩写?初始化散发是一个什么样的过程?

从es的官方网站我们可以指定,初始化散发其实就是在进行真正的查询之前,先把各个分片的词频率和文档频率收集一下,然后进行词搜索的时候,各分片依据全局的词频率和文档频率进行搜索和排名。显然如果使用DFS_QUERY_THEN_FETCH这种查询方式,效率是最低的,因为一个搜索,可能要请求3次分片。但,使用DFS方法,搜索精度应该是最高的。 
至于DFS是什么缩写,没有找到相关资料,这个D可能是Distributed,F可能是frequency的缩写,至于S可能是Scatter的缩写,整个单词可能是分布式词频率和文档频率散发的缩写。 
总结一下,从性能考虑QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。从搜索的准确度来说,DFS要比非DFS的准确度更高。

最后来看下源码:

public enum SearchType {
    /**
     * Same as {@link #QUERY_THEN_FETCH}, except for an initial scatter phase which goes and computes the distributed
     * term frequencies for more accurate scoring.
     */
    DFS_QUERY_THEN_FETCH((byte) 0),
    /**
     * The query is executed against all shards, but only enough information is returned (not the document content).
     * The results are then sorted and ranked, and based on it, only the relevant shards are asked for the actual
     * document content. The return number of hits is exactly as specified in size, since they are the only ones that
     * are fetched. This is very handy when the index has a lot of shards (not replicas, shard id groups).
     */
    QUERY_THEN_FETCH((byte) 1),
    /**
     * Same as {@link #QUERY_AND_FETCH}, except for an initial scatter phase which goes and computes the distributed
     * term frequencies for more accurate scoring.
     */
    DFS_QUERY_AND_FETCH((byte) 2),
    /**
     * The most naive (and possibly fastest) implementation is to simply execute the query on all relevant shards
     * and return the results. Each shard returns size results. Since each shard already returns size hits, this
     * type actually returns size times number of shards results back to the caller.
     */
    QUERY_AND_FETCH((byte) 3),
    /**
     * Performs scanning of the results which executes the search without any sorting.
     * It will automatically start scrolling the result set.
     * @deprecated will be removed in 3.0, you should do a regular scroll instead, ordered by `_doc`
     */
    @Deprecated
    SCAN((byte) 4),
    /**
     * Only counts the results, will still execute aggregations and the like.
     * @deprecated does not any improvements compared to {@link #QUERY_THEN_FETCH} with a `size` of {@code 0}
     */
    @Deprecated
    COUNT((byte) 5);

    /**
     * The default search type ({@link #QUERY_THEN_FETCH}.
     */


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值