ElasticSearch版本:6.5.0(点击跳转官方文档)
一个搜索请求必须询问请求的索引中所有分片的某个副本来进行匹配。
假设一个索引有5个主分片,每个主分片有l个副分片,共10个分片,一次搜索请求会由5个分片来共同完成;它们可能是主分片,也可能是副分片。也就是说,一次搜索请求只会命中所有分片副本中的一个。
Elasticsearch 检索分为两个阶段:Query阶段 和 Fetch阶段。
1. Query阶段
转发请求:协调节点 接收到用户检索请求后,将检索请求转发给相关索引的任意节点(主分片、副本分片都有可能)。
执行查询:数据节点 收到查询请求执行查询,并对结果进行排序。(每个节点都会根据请求中参数返回from+size个排序后的文档Id和排序值给协调节点 )
查询阶段并不会对搜索请求的内容进行解析,无论搜索什么内容,只看本次搜索需要命中哪些 shard(分片),然后针对每个特定 shard(分片),转发搜索请求 。
2. Fetch阶段
- 重排序:协调节点 收到数据节点 返回的数据后,按照排序值 对所有分片取回的数据进行重排序,最终只选取客户端需要的from+size个文档的Id
- 获取文档数据:协调节点 根据选取的文档id,到相应的分片获取详细文档数据,并将最终结果集返回用户。
3. Search Type
执行分布式搜索时,需要将搜索操作分散到所有相关的分片节点上,然后将所有结果收集回去。
场景一:假如我们有10个分片,第一个分片可能会保存0到10之间最相关的结果,其他分片的结果排在其后。但是,在执行请求时,我们需要从所有分片中获取0到10之间的结果,对它们进行排序,然后返回结果。
场景二:如果要支持准确排名,则需要首先从所有分片中收集词频,以计算全局词频,然后使用这些全局频率对每个分片执行查询。
由于需要对结果集进行排序,因此在保持正确的排序行为的同时获取较大的文档集甚至滚动(scroll)它可能是非常昂贵的操作。
Elasticsearch允许根据每个搜索请求控制要执行的搜索类型。可以通过在查询字符串中设置search_type参数来配置类型。
3.1. QUERY_THEN_FETCH
默认的SearchType(仅针对6.5.0版本) ,分为两步:
第一步:协调节点 向索引相关的分片发出请求,各分片只返回文档、排序值等相关信息(from+size);
第二步:协调节点 根据排序值,对所有相关分片返回值进行排序后,再用文档id,去相关分片获取文档数据,返回用户。
3.2. DFS_QUERY_THEN_FETCH
同 QUERY_THEN_FETCH 类似,只多了一个步骤。
在 协调节点 向索引相关的分片发出请求之前,先对所有分片发送请求,把所有分片中词频、文频率等打分依据全部汇总,再执行后面的操作。
该策略效率最低,性能最差,但结果最准确(精度最高)。
3.3. QUERY_AND_FETCH
Only used for pre 5.3 request where this type is still needed
协调节点 向索引相关的分片发出请求,各分片将文档数据、排序值 等所有信息一起返回。
这种搜索方式是最快的,相比上面两种方式,只需要去分片查询一次;但各个分片返回的结果集之和,可能是用户要求size的n倍。