ES 分布式搜索的运行机制
ES 有两种 search_type
即搜索类型:git
query_then_fetch
(默认)
dfs_query_then_fetch
query_then_fetch

- 用户发起搜索,请求到集群中的某个节点。
- query 会被发送到全部相关的 shard 分片上。
- 每一个 shard 分片独立执行 query 搜索文档并进行排序分页等,打分时使用的是分片自己的
Local
Term/Document 频率。
- 分片的 query 结果(只有元数据,例如
_id
和 _score
)返回给请求节点。
- 请求节点对全部分片的 query 结果进行汇总,而后根据打分排序和分页,最后选择出搜索结果文档(也只有元数据)。
- 根据元数据去对应的 shard 分片拉取存储在磁盘上的文档的详细数据。
- 获得详细的文档数据,组成搜索结果,将结果返回给用户。
缺点:因为每一个分片独立使用自身的而不是全局的 Term/Document 频率进行相关度打分,当数据分布不均匀时可能会形成打分误差,从而影响最终搜索结果的相关性。github
dfs_query_then_fetch

dfs_query_then_fetch
与 query_then_fetch
的运行机制很是相似,可是有两点不一样。网络
- 用户发起搜索,请求到集群中的某个节点。
- 预查询每一个分片,获得全局的 Global Term/Document 频率。
- query 会被发送到全部相关的 shard 分片上。
- 每一个 shard 分片独立执行 query 搜索文档并进行排序分页等,打分时使用的是分片自己的
Global
Term/Document 频率。
- 分片的 query 结果(只有元数据,例如
_id
和 _score
)返回给请求节点。
- 请求节点对全部分片的 query 结果进行汇总,而后根据打分排序和分页,最后选择出搜索结果文档(也只有元数据)。
- 根据元数据去对应的 shard 分片拉取存储在磁盘上的文档的详细数据。
- 获得详细的文档数据,组成搜索结果,将结果返回给用户。
缺点:太耗费资源,通常仍是不建议使用。分布式
经验
- 虽然 ES 有两种搜索类型,但通常仍是都用默认的
query_then_fetch
。
- 当数据量没有足够大的状况下(好比搜索类型数据 20GB,日志类型数据 20-50GB),设置一个 shard 主分片是比较推荐的,只设置一个主分片,你会发现搜索时省掉了好多事情。
- 不须要文档数据时,使用
_source: false
能够避免请求节点到非本机分片的网络耗时以及读取磁盘文件的耗时。
- 使用 from + size 分页时,假设你只须要前 10k 条数据里的最后十条,那么每一个分片也会取 10k 条数据,若是你的索引有 5 个主分片,那么汇总时就有 5 * 10k = 50k 条数据,这 50k 条数据是在内存里进行排序和最后的分页的,因此深度分页也是比较吃资源的。
