目录
近期由于业务涉及的数据量比较大,进行查询时返回的结果集非常大,但是当查询一万条以后的详细内容时,发现出错,后台日志提示最大的查询量不应该超过10000条,究竟是为什么呢,要做这样一个限制,于是就查阅了资料。
一、查询阶段:
在初始化查询阶段(query phase),查询被向索引中的每个分片副本(原本或副本)广播。每个分片在本地执行搜索并且建立了匹配document的优先队列(priority queue)。
-
优先队列
-
-
一个优先队列(priority queue is)只是一个存有前n个(top-n)匹配
document的有序列表。这个优先队列的大小由分
-
-
页参数
from和size决定。例如,下面这个例子中的搜索请求要求优先队列要能够容纳
100个
document
-
-
GET /_search
-
{
-
"from":
90,
-
"size":
10
-
}
这个查询的过程被描述在图分布式搜索查询阶段中。
查询阶段包含以下三步:
1.客户端发送一个 search(搜索) 请求给 Node 3 , Node 3 创建了一个长度为 from+size 的空优先级队列。
2. Node 3 转发这个搜索请求到索引中每个分片的原本或副本。每个分片在本地执行这个查询并且结果将结果到一个大小为 from+size 的有序本地优先队列里去。
3.每个分片返回document的ID和它优先队列里的所有document的排序值给协调节点 Node 3 。 Node 3 把这些值合并到自己的优先队列里产生全局排序结果。
当一个搜索请求被发送到一个节点Node,这个节点就变成了协调节点。这个节点的工作是向所有相关的分片广播搜索请求并且把它们的响应整合成一个全局的有序结果集。这个结果集会被返回给客户端。
第一步是向索引里的每个节点的分片副本广播请求。就像document的 GET 请求一样,搜索请求可以被每个分片的原本或任意副本处理。这就是更多的副本(当结合更多的硬件时)如何提高搜索的吞吐量的方法。对于后续请求,协调节点会轮询所有的分片副本以分摊负载。
每一个分片在本地执行查询和建立一个长度为 from+size 的有序优先队列——这个长度意味着它自己的结果数量就足够满足全局的请求要求。分片返回一个轻量级的结果列表给协调节点。只包含documentID值和排序需要用到的值,例如 _score 。协调节点将这些分片级的结果合并到自己的有序优先队列里。这个就代表了最终的全局有序结果集。到这里,查询阶段结束。
-
注意:
-
一个索引可以由一个或多个原始分片组成,所以一个对于单个索引的搜索请求也需要能够把来自多个分片的结果组合
-
起来。一个对于 多(multiple)或全部(all)索引的搜索的工作机制和这完全一致——仅仅是多了一些分片而已。
二、取回阶段:
查询阶段辨别出那些满足搜索请求的document,但我们仍然需要取回那些document本身。这就是取回阶段的工作,如图分布式搜索的取回阶段所示。
分发阶段由以下步骤构成:
1.协调节点辨别出哪个document需要取回,并且向相关分片发出 GET 请求。
2.每个分片加载document并且根据需要丰富(enrich)它们,然后再将document返回协调节点。
3.一旦所有的document都被取回,协调节点会将结果返回给客户端。
协调节点先决定哪些document是实际(actually)需要取回的。例如,我们指定查询 { "from": 90, "size": 10 } ,那么前90条将会被丢弃,只有之后的10条会需要取回。这些document可能来自与原始查询请求相关的某个、某些或者全部分片。
协调节点为每个持有相关document的分片建立多点get请求然后发送请求到处理查询阶段的分片副本。
分片加载document主体—— _source field。如果需要,还会根据元数据丰富结果和高亮搜索片断。一旦协调节点收到所有结果,会将它们汇集到单一的回答响应里,这个响应将会返回给客户端。
三、 深分页
查询然后取回过程虽然支持通过使用 from 和 size 参数进行分页,但是要在有限范围内(within limited)。还记得每个分片必须构造一个长度为 from+size 的优先队列吧,所有这些都要传回协调节点。这意味着协调节点要通过对 分片数量 * (from +size)个document进行排序来找到正确的 size 个document。
比如:根据document的数量,分片的数量以及所使用的硬件,对10,000到50,000条结果(1,000到5,000页)深分页是可行的。是对于足够大的 from 值,排序过程将会变得非常繁重,会使用巨大量的CPU,内存和带宽。因此,强烈不建议使用深分页。在实际中,“深分页者”也是很少的一部人。一般人会在翻了两三页后就停止翻页,并会更改搜索标准。那些不正常情况通是机器人或者网络爬虫的行为。它们会持续不断地一页接着一页地获取页面直到服务器到底崩溃的边缘。
如果你确实需要从集群里获取大量documents,你可以通过设置搜索类型 scan 禁用排序,来高效地做这件事。这一点将在后面的讨论。
综合:ES的深分页需要处理大量的数据,计算复杂度较高,性能会受到极大影响,因此ES底层对查询的数据量做了限制,不建议使用该种方式处理大量数据。一些搜索引擎每次查询返回的数据也是有限制的,就是这个原因。每一项技术都有它的优缺点和局限性。
转载:https://blog.csdn.net/weixin_39734304/article/details/106051915