Elasticsearch分布式检索原理笔记 2022-10-24 05:51 112阅读 0赞 **目录** ES检索的两阶段过程 查询阶段 取回阶段 深分页问题 scroll search\_after -------------------- ## ES检索的两阶段过程 ## 文档的唯一性可以由 \_index(索引名称)和 \_id(文档id)的组合来确定,这表示我们可以确切知道集群中哪个分片含有此文档。 而当我们需要通过id之外的条件进行搜索时,就需要一种更加复杂的执行模型,因为我们不知道查询会命中哪些文档,这些文档有可能在集群的任何分片上。一个搜索请求必须询问我们关注的索引的所有分片的某个副本来确定它们是否含有任何匹配的文档。 但是找到所有的匹配文档仅仅完成事情的一半。 在 `search` 接口返回一个 `page` 结果之前,多分片中的结果必须组合成单个排序列表。 为此,搜索被执行成一个两阶段过程:*query then fetch* ### 查询阶段 ### 在初始 *查询阶段* 时, 查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的 *优先队列*(一个 *优先队列* 仅仅是一个存有 *top-n* 匹配文档的有序列表。优先队列的大小取决于分页参数 `from` 和 `size`)。 当一个搜索请求被发送到某个节点时,这个节点就变成了协调节点。 这个节点的任务是广播查询请求到所有相关分片并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。 查询阶段包含以下三个步骤: 1. 客户端发送一个 `search` 请求到 `Node 3` , `Node 3` 会创建一个大小为 `from + size` 的空优先队列。 2. `Node 3` 将查询请求转发到索引的每个主分片或副本分片中。每个分片在本地执行查询并添加结果到大小为 `from + size` 的本地有序优先队列中。 3. 每个分片返回各自优先队列中所有文档的 ID 和排序值给协调节点,也就是 `Node 3` ,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEyMTIzOTQ_size_16_color_FFFFFF_t_70][] ### 取回阶段 ### 查询阶段标识哪些文档满足搜索请求,但是我们仍然需要取回这些文档,这是取回阶段的任务。 取回阶段由以下步骤构成: 1. 协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 `GET` 请求。 2. 每个分片加载并 *丰富* 文档,如果有需要的话,接着返回文档给协调节点。 3. 一旦所有的文档都被取回了,协调节点返回结果给客户端。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEyMTIzOTQ_size_16_color_FFFFFF_t_70 1][] ## 深分页问题 ## > 先查后取的过程支持用 `from` 和 `size` 参数分页,但是这是 *有限制的* 。 要记住需要传递信息给协调节点的每个分片必须先创建一个 `from + size` 长度的队列,协调节点需要根据 `number_of_shards * (from + size)` 排序文档,来找到被包含在 `size` 里的文档。 > > 取决于你的文档的大小,分片的数量和你使用的硬件,给 10,000 到 50,000 的结果文档深分页( 1,000 到 5,000 页)是完全可行的。但是使用足够大的 `from` 值,排序过程可能会变得非常沉重,使用大量的CPU、内存和带宽。因为这个原因,我们强烈建议你不要使用深分页。 > > 实际上, “深分页” 很少符合人的行为。当2到3页过去以后,人会停止翻页,并且改变搜索标准。会不知疲倦地一页一页的获取网页直到你的服务崩溃的罪魁祸首一般是机器人或者web spider。 解决深分页问题一般会用两种方式:scroll 或 search\_after ### scroll ### scroll 类似于sql中的cursor,使用scroll,每次只能获取一页的内容,然后会返回一个scroll\_id。根据返回的这个scroll\_id可以不断地获取下一页的内容,所以 scroll 并不适用于有跳页的情景。 深度分页的代价根源是每次查询,都需要将结果集全局排序,如果去掉全局排序的特性的话查询结果的成本就会很低。而 scroll 就是一次把要用的数据都排完了,分批取出,从而达到性能的提升。 因此,scroll 查询取的是某个时间点的快照数据,查询初始化之后索引上的任何变化会被它忽略。 scroll 并不适合实时查询,适合于后台数据批量遍历计算的场景。 GET /old_index/_search?scroll=1m { "query": { "match_all": {}}, "sort" : ["_doc"], "size": 100 } * 1m 指 scroll\_id 保留1分钟可用; * sort 为排序的字段,关键字 `_doc` 是最有效的排序顺序; * size 为每次返回的数量,from不需要指定,或指定为0。 这个查询的返回结果包括一个字段 `_scroll_id`, 它是一个base64编码的长字符串。现在我们能传递字段 `_scroll_id` 到 `_search/scroll` 查询接口获取下一批结果: GET /_search/scroll { "scroll": "1m", "scroll_id" : "cXVlcnlUaGVuRmV0Y2g7NTsxMDk5NDpkUmpiR2FjOFNhNnlCM1ZDMWpWYnRROzEwOTk1OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MTA5OTM6ZFJqYkdhYzhTYTZ5QjNWQzFqVmJ0UTsxMTE5MDpBVUtwN2lxc1FLZV8yRGVjWlI2QUVBOzEwOTk2OmRSamJHYWM4U2E2eUIzVkMxalZidFE7MDs=" } ### search\_after ### 想要实现实时的滚动分页,可以通过search\_after来实现。 search\_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到结果上。但是需要注意,因为每一页的数据依赖于上一页最后一条数据,所以无法实现跳页请求。 为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 \_id 作为全局唯一值。 GET /test_index/_search { "query": { "match_all": {} }, "size": 10, "search_after":[1003], "sort": [ { "_id": { "order": "desc" } } ] } * search\_after 对应的值是上一次查询最后一条记录中 sort 字段的值; * from属性可以省略,或者是0或-1; * sort 对应的字段应该是全局唯一的,推荐使用\_id。 *笔记内容基于官方文档整理:[https://www.elastic.co/guide/cn/elasticsearch/guide/current/distributed-search.html][https_www.elastic.co_guide_cn_elasticsearch_guide_current_distributed-search.html]* [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEyMTIzOTQ_size_16_color_FFFFFF_t_70]: /images/20221024/7929b4c09e2940b2ad690615eb00d1fa.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEyMTIzOTQ_size_16_color_FFFFFF_t_70 1]: /images/20221024/a528a1abdc384845b7f2b52d67cf361a.png [https_www.elastic.co_guide_cn_elasticsearch_guide_current_distributed-search.html]: https://www.elastic.co/guide/cn/elasticsearch/guide/current/distributed-search.html
相关 Elasticsearch 亿级数据检索案例与原理 优质文章,及时送达 ![640?wx\_fmt=jpeg][640_wx_fmt_jpeg] 来源 | mikevictor 链接 | cnblogs.com/mikev 爱被打了一巴掌/ 2021年07月31日 13:45/ 0 赞/ 331 阅读
相关 elasticsearch(es)分布式全文检索引擎 简介 0. 带着问题上路—ES是如何产生的? -------------------- (1)思考:大规模数据如何检索? 如:当系统数据量上了10亿、100亿条的时候,我们 逃离我推掉我的手/ 2021年08月19日 21:32/ 0 赞/ 1303 阅读
相关 Elasticsearch原理学习--为什么Elasticsearch/Lucene检索可以比MySQL快? 转载:[https://blog.csdn.net/qq924862077/article/details/80382634][https_blog.csdn.net_qq92 待我称王封你为后i/ 2022年01月22日 02:45/ 0 赞/ 110 阅读
相关 springboot 与检索—使用、原理、整合ElasticSearch ElasticSearch--全文搜索引擎的首选:面向文档,它存储整个对象或文档。使用json作为文档的序列化格式(一个json文档就代表一个对象)。 朱雀/ 2022年05月08日 09:04/ 0 赞/ 183 阅读
相关 Elasticsearch 检索技术 [https://blog.csdn.net/laoyang360/article/category/6239824][https_blog.csdn.net_laoyang3 深碍√TFBOYSˉ_/ 2022年05月13日 16:23/ 0 赞/ 122 阅读
相关 Elasticsearch原理学习--为什么Elasticsearch/Lucene检索可以比MySQL快? 同样都可以对数据构建索引并通过索引查询数据,为什么Lucene或基于Lucene的Elasticsearch会比关系型数据库如MySQL搜索性能更优?两者有什么区别?各自选型的 今天药忘吃喽~/ 2022年05月24日 04:10/ 0 赞/ 42 阅读
相关 Elasticsearch学习笔记(七)Elasticsearch分布式集群工作原理简介 文章目录 Elasticsearch系列文章目录 路由 修改(新建、索引和删除文档)索引时请求的路由情况 \`replication\ 谁借莪1个温暖的怀抱¢/ 2022年07月11日 12:17/ 0 赞/ 84 阅读
相关 【Elasticsearch】Elasticsearch 分布式一致性原理分析:元数据 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ub àì夳堔傛蜴生んèń/ 2022年08月31日 10:00/ 0 赞/ 55 阅读
相关 ElasticSearch学习笔记(四) 检索相关 查询字段解析: \_search:我们可以使用\_search API来检索查询索引。搜索API的最基础的形式是没有指定任何查询的空搜索,它简单地返回集群中所有索引下的所 不念不忘少年蓝@/ 2022年10月05日 10:54/ 0 赞/ 94 阅读
相关 Elasticsearch分布式检索原理笔记 目录 ES检索的两阶段过程 查询阶段 取回阶段 深分页问题 scroll search\_after -------------------- ES检索的两 曾经终败给现在/ 2022年10月24日 05:51/ 0 赞/ 113 阅读
还没有评论,来说两句吧...