当前位置: 首页 > article >正文

Elasticsearch 深入分析三种分页查询【Elasticsearch 深度分页】

前言:

在前面的 Elasticsearch 系列文章中,分享了 Elasticsearch 的各种查询,分页查询也分享过,本篇将再次对 Elasticsearch 分页查询进行专题分析,“深度分页” 这个名词对于我们来说是一个非常常见的业务场景,本篇再次进行 Elasticsearch 分页查询进行分析,也是围绕深度分页这个业务场景来展开的。

Elasticsearch 系列文章传送门

Elasticsearch 基础篇【ES】

Elasticsearch Windows 环境安装

Elasticsearch 之 ElasticsearchRestTemplate 普通查询

Elasticsearch 之 ElasticsearchRestTemplate 聚合查询

Elasticsearch 之 ElasticsearchRestTemplate 嵌套聚合查询【嵌套文档聚合查询】

分页查询前景回顾

我们来回忆下在之前的分页查询,代码如下:

public List<CarDO> pageList(int currentPage, int pageSize) {NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();queryBuilder.withPageable(PageRequest.of(currentPage - 1, pageSize)).build();queryBuilder.withQuery(QueryBuilders.matchQuery("color", "雅灰"));SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.build(), CarDO.class);return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

以上代码我们使用了 【queryBuilder.withPageable】来实现的分页查查询,通过 PageRequest 传入了当前页和分页大小构建了一个分页对象,以上分页会有什么问题?

Elasticsearch 分页原理探讨

Elasticsearch 分页官方文档

官方文档描述如下:

在这里插入图片描述

官方文档说的大概意思如下:

默认情况下,搜索会返回前 10 个匹配结果,如果要翻阅更多结果,可以使用搜索 API 的 from 和 size 参数来实现。from 参数定义要跳过的匹配数,默认为 0。size 参数是返回的最大匹配数,这两个参数一起定义了一页结果。
但是要避免使用 from 和 size 分页太深或一次请求太多结果的情况。搜索请求通常跨越多个分片。每个分片必须将其请求的命中和任何先前页面的命中加载到内存中。对于深层页面或大量结果,这些操作可能会显著增加内存和 CPU 使用率,从而导致性能下降或节点故障。
默认情况下,不能使用 from 和 size 来翻阅超过 10000 个匹配结果。此限制是 index.max_result_window 索引设置设定的一项保障措施。如果您需要翻阅超过 10,000 个匹配项,请使用 search_after 来实现。

简单概括就是 Elasticsearch 使用的 from 和 size 来实现分页,但是不建议使用 from 和 size 这种方式来实现深度分页,当分页深度超过 10000 的时候就不建议使用 from 和 size 来实现了,否则会大量占用内存和 CPU,也就是说我们上面的分页在深度分页的时候会有性能问题。

Elasticsearch 分页的内部执行过程分析

在 Elasticsearch 搜索是一个两阶段的过程,分别为查询阶段和取回阶段。

查询阶段

  1. 广播查询请求:客户端发送查询请求到某个节点,该节点会将查询请求广播到索引的所有分片上。
  2. 分片处理:每个分片在本地执行独立查询,根据查询条件得到符合条件的文档,并会为每个文档计算得分,每个分片中会按照得分来对文档进行排序,然后保留得分靠前的文档 ID。
  3. 合并结果:各分片将本地的部分结果返回给协调节点,协调节点会对这些结果进行合并排序,得到需要返回的额文档 ID。

取回阶段

  1. 获取文档详情:根据文档 ID,向包含这些文档的分片发送查询请求,获取文档的详细内容。
  2. 返回结果到客户端:协调节点在收到所有的文档内容后,再进行整理得到最终的文档,返回给客户端。

Elasticsearch 分页过程的问题

假设在一个有 3 个主分片的索引中进行分页搜索,每 10 个文档为一页数据,当请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,返回给协调节点 ,协调节点对 30 个结果排序得到全部结果的前 10 个,这个并没有什么问题。

当我们请求第 1000 页的时候,就需要每个分片返回 10001 到 10010 的文档,然后返回给协调节点,最后协调节点对全部 30030 个结果排序,最后丢弃掉这些结果中的 30020 个结果,很明显这里有一个非常大的内存占用的浪费,这就是 from 和 size 方式分页的问题,也就是我们常说的深度分页问题。

Elasticsearch 分页之 Search After

Elasticsearch 官方文档关于 Search After 的介绍比较多,这里简单截图如下,想了解更多点击以下超链接跳转。

Elasticsearch 分页官方文档

Elasticsearch 分页之 Search after

在这里插入图片描述

Elasticsearch 的 Search after 的分页是基于上一次查询结果的最后一条数据的指定字段值来进行下一页数据的查询,它通过在查询请求中指定 search_after 参数来实现。与传统的分页方式(from 和 size 参数)不同,Search after 不需要记录页码,也不会受到 from + size 的深度限制,能更高效地处理深层分页问题,因为每一页的数据依赖于上一页最后一条数据,所以无法进行跳页。

Java API 使用 Elasticsearch 的 search_after 实现分页

我们上面了解了 Elasticsearch 的 search_after 分页原理,现在我们使用 Java API 实现分页。代码如下:

@Autowired
private RestHighLevelClient restHighLevelClient;@Override
public List<CarDO> searchAfter(int lastId, int pageSize) {//使用 searchAfter 分页SearchRequest searchRequest = new SearchRequest("car_7");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//查询所有的数据searchSourceBuilder.query(QueryBuilders.matchAllQuery());//使用 search after 分页需要设置 from 为 0searchSourceBuilder.from(0);searchSourceBuilder.size(pageSize);searchSourceBuilder.searchAfter(new Object[]{lastId});//设置超时时间 超过 60秒还没有返回则返回一个超时错误searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));//定义排序规则SortBuilder<FieldSortBuilder> id4Sort = SortBuilders.fieldSort("id").order(SortOrder.ASC);searchSourceBuilder.sort(id4Sort);searchRequest.source(searchSourceBuilder);List<CarDO> carList = new ArrayList<>();try {SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);org.elasticsearch.search.SearchHit[] hits = search.getHits().getHits();if (Objects.nonNull(hits) && hits.length > 0) {//下一次分页的起始点lastId = Integer.parseInt(hits[hits.length - 1].getSortValues()[0].toString());}for (org.elasticsearch.search.SearchHit hit : hits) {Map<String, Object> sourceAsMap = hit.getSourceAsMap();CarDO carDO = JSON.parseObject(JSON.toJSONString(sourceAsMap), CarDO.class);carDO.setLastId(lastId);carList.add(carDO);}} catch (IOException e) {e.printStackTrace();}return carList;
}

我们来分析一下上面这段代码:

  • lastId:上一次查询的最后一个 id,我们需要使用这个 id 来查询下一页的数据。
  • pageSize:每页显示的条数。
  • from:从第几条开始查询,使用 search_after 的时候需要设置为 0。
  • searchSourceBuilder.searchAfter(new Object[]{lastId}):从 lastId 开始查询,用于指定分页的起始位置,它接收上一页最后一条数据的排序值数组。
  • searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)):设置超时时间,超过 60 秒还没有返回则返回一个超时错误。
  • searchSourceBuilder.sort(id4Sort):指定排序的字段和顺序,用于确定 search_after 分页的顺序,这里我们按照 id 排序,使用 search_after 进行分页查询,必须定义一个排序字段。也可以指定按照某个日期字段升序或降序排序,或者按照多个字段的组合排序,排序字段的选择要确保在整个查询过程中能够唯一标识每一条数据。

以上就是使用 search_after 实现 Elasticsearch 分页的核心代码的解释。

scroll-search 分页

Elasticsearch 还提供了 scroll-search 的方式来实现分页,官方文档如下:

scroll-search 分页官方文档

在这里插入图片描述

官方文档不建议使用 scroll-search 实现 Elasticsearch 深度分页,推荐使用 search_after 实现深度分页,因为官方文档已经不在推荐使用,这里就不在对 scroll-search 分页进行代码演示了,这里只简单对 scroll-search 进行简单优缺点分析如下:

优点:

  • 深度分页性能较好:可以满足大量数据的深度分页场景,在处理深度分页时性能稳定,不会像 from/size 分页那样,随着分页深度的增加,ES 需要遍历和丢弃的文档增多而导致性能显著下降(但已不推荐使用,推荐使用 search_after 来实现)。
  • 打破结果窗口限制:不受 index.max_result_window 限制,能方便地进行全量数据的遍历处理,可用于导出大量数据操作。
  • 查询结果稳定性好:因为 scroll-search 基于快照查询,在整个 scroll 查询过程中,只要快照有效,查询结果是稳定的,不会出现遗漏或重复数据的情况,对于需要准确获取大量数据但对数据实时性要求不敏感的场景非常实用。

缺点:

  • 数据实时性差:因为 scroll-search 是基于快照查询,Scroll 上下文维护的搜索结果是在快照创建时的数据状态,因此有可能查询到的不是最新的数据,不适合数据实时性要求高的业务场景。
  • 内存占用问题:因为 scroll-search 是基于快照查询,需要维护快照,会占用额外的内存资源,如果处理的数据量非常大,可能会对服务器内存造成较大压力,需要合理设置相关参数并关注服务器资源使用情况。
  • 数据过期问题:scroll-search 查询结果是快照查询,如果快照过期,过期后需要重新初始化查询,会导致整个过程变的更为复杂。
  • 不支持跳页。

总结:本篇分享了 Elasticsearch 三种分页方式的实现,并对两种常用的分页方式进行了代码演示,深度分页推荐使用 search_after 的方式实现,希望可以帮助到对 Elasticsearch 分查询不太熟悉的朋友。

如有不正确的地方欢迎各位指出纠正。

相关文章:

Elasticsearch 深入分析三种分页查询【Elasticsearch 深度分页】

前言&#xff1a; 在前面的 Elasticsearch 系列文章中&#xff0c;分享了 Elasticsearch 的各种查询&#xff0c;分页查询也分享过&#xff0c;本篇将再次对 Elasticsearch 分页查询进行专题分析&#xff0c;“深度分页” 这个名词对于我们来说是一个非常常见的业务场景&#…...

DAY29 超大力王爱学Python

知识点回顾 类的装饰器装饰器思想的进一步理解&#xff1a;外部修改、动态类方法的定义&#xff1a;内部定义和外部定义 作业&#xff1a;复习类和函数的知识点&#xff0c;写下自己过去29天的学习心得&#xff0c;如对函数和类的理解&#xff0c;对python这门工具的理解等&…...

Ubuntu 远程桌面配置指南

概述: 本文主要介绍在Ubuntu 22.04中通过VNC实现远程连接的方法。首先需安装图形化界面和VNC工具x11vnc,设置开机启动服务;然后在Windows客户端用VNC Viewer通过局域网IP和端口5900连接。 总结: 一、VNC配置与安装 安装图形化界面 在Ubuntu 22.04中需先安装: sudo apt …...

【Python装饰器深度解析】从语法糖到元编程实战

目录 🌟 前言🏗️ 技术背景与价值🩹 当前技术痛点🛠️ 解决方案概述👥 目标读者说明🧠 一、技术原理剖析📊 核心概念图解💡 核心作用讲解🔧 关键技术模块说明⚖️ 技术选型对比🛠️ 二、实战演示⚙️ 环境配置要求💻 核心代码实现案例1:基础计时装饰器案…...

推扫式高光谱相机VIX-N230重磅发布——开启精准成像新时代

随着各行业对高光谱成像技术需求的持续增长&#xff0c;市场对于高分辨率、高灵敏度以及快速成像的高光谱相机的需求愈发迫切。中达瑞和凭借多年的行业经验和技术积累&#xff0c;敏锐捕捉到这一市场趋势&#xff0c;正式推出全新一代推扫式可见光近红外高光谱相机——VIX-N230…...

Parsec解决PnP连接失败的问题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、准备环境二、DMZ三、端口映射1.Parsec设置固定端口2.路由器设置端口转发3.重启被控端Parsec四、多少一句1.有光猫管理员账号2.没有光猫管理员账号总结 前言…...

面试题:详细分析Arraylist 与 LinkedList 的异同

相同点 都是List接口的实现类&#xff1a; ArrayList和LinkedList都实现了Java集合框架中的List接口&#xff0c;因此它们都提供了对列表元素的操作方法。 都继承了Collection接口&#xff1a; 由于List接口继承了Collection接口&#xff0c;所以ArrayList和LinkedList也都继承…...

软件I2C

软件I2C 注意&#xff1a; SDA&#xff08;串行数据线&#xff09;和SCL&#xff08;串行时钟线&#xff09;都是双向I/O线&#xff0c;接口电路为开漏输出。需通过上拉电阻接电源VCC。 软件I2C说明 说明&#xff0c;有的单片机没有硬件I2C的功能&#xff0c;或者因为电路设计…...

通过实例讲解螺旋模型

目录 一、螺旋模型的核心概念 二、螺旋模型在电子商城系统开发中的应用示例 第 1 次螺旋:项目启动与风险初探...

Brooks Polycold快速循环水蒸气冷冻泵客户使用手含电路图,适用于真空室应用

Brooks Polycold快速循环水蒸气冷冻泵客户使用手含电路图&#xff0c;适用于真空室应用...

winfrom中创建webapi

参照一下两篇 Winform窗体利用WebApi接口实现ModbusTCP数据服务_winform webapi-CSDN博客 C#.NET WebApi返回各种类型(图片/json数据/字符串)&#xff0c;.net图片转二进制流或byte - 冰封的心 - 博客园...

unity XCharts插件生成曲线图在UICanvas中

【推荐100个unity插件之22】基于UGUI的功能强大的简单易用的Unity数据可视化图表插件——XCharts3.0插件的使用_unity xcharts-CSDN博客...

Pichome 开源网盘程序index.php 文件读取漏洞(CVE-2025-1743)

免责声明 本文档所述漏洞详情及复现方法仅限用于合法授权的安全研究和学术教育用途。任何个人或组织不得利用本文内容从事未经许可的渗透测试、网络攻击或其他违法行为。使用者应确保其行为符合相关法律法规,并取得目标系统的明确授权。 对于因不当使用本文信息而造成的任何直…...

关于在Unity项目中使用Post Processing插件打包到web端出现的问题

关于在Unity项目中使用Post Processing插件打包到web端出现的问题 解决方法&#xff1a;是不激活摄像机上的Post Processing有关组件&#xff0c;拉低场景中的Directional Light平行光的强度进行web端打包。 &#xff08;烘焙灯光时是可以激活。&#xff09; web端支持这个Pos…...

Prompt Tuning:高效微调大模型的新利器

Prompt Tuning(提示调优)是什么 Prompt Tuning(提示调优) 是大模型参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)的重要技术之一,其核心思想是通过优化 连续的提示向量(而非整个模型参数)来适配特定任务。以下是关于 Prompt Tuning 的详细解析: 一、核心概念…...

OpenCV 第6课 图像处理之几何变换(重映射)

1. 概述 简单来说,重映射就是把一副图像内的像素点按照规则映射到到另外一幅图像内的对应位置上去,形成一张新的图像。 因为原图像与目标图像的像素坐标不是一一对应的。一般情况下,我们通过重映射来表达每个像素的位置(x,y),像这样: g(x,y)=f(h(x,y)) 在这里g()是目标图…...

C++初阶-vector的底层

目录 1.序言 2.std::sort(了解) 3.vector的底层 3.1讲解 3.2构造函数 3.3push_back函数 3.4begin()和end()函数 3.5capacity()和size()函数和max_size函数 3.5.1size&#xff08;&#xff09;函数 为什么这样写&#xff1f; 底层原理 3.5.2max_size()函数 为什么这…...

获取文件夹下所有文件的名称

一、为什么写这个程序 因为我要做一个类似于目录树的结构&#xff0c;需要把文件夹下的所有名字全部导出了。 二、Python和vscode的安装 先安装Python在安装vscode Python安装 vscode的安装 三、源码 import os# 定义要扫描的文件夹列表&#xff08;使用原始字符串避免转义…...

C语言指针深入详解(五):回调函数、qsort函数

目录 一、回调函数 1、使用回调函数改造前 2、使用回到函数改造后 二、qsort使用举例 1、使用qsort函数排序整型数据 2、使用qsort排序结构数据 三、qsort函数模拟实现 结语 &#x1f525;个人主页&#xff1a;艾莉丝努力练剑 &#x1f353;专栏传送门&#xff1a;《…...

数据结构进阶:AVL树与红黑树

目录 前言 AVL树 定义 结构 插入 AVL树插入的大致过程 更新平衡因子 旋转 右单旋 左单旋 左右双旋 右左双旋 实现 红黑树 定义 性质 结构 插入 实现 总结 前言 在学习了二叉搜索树之后&#xff0c;我们了解到其有个致命缺陷——当树的形状呈现出一边倒…...

容器化-K8s-镜像仓库使用和应用

一、K8s 镜像仓库使用 1、启动镜像仓库 cd/usr/local/harbor ./install.sh2、配置镜像仓库地址 在 master 节点和 slaver 节点上,需要配置 Docker 的镜像仓库地址,以便能够访问本地的镜像仓库。编辑 Docker 的配置文件 vi /etc/docker/daemon.json(如果不存在则创建),添…...

基于Spring Boot + Vue的教师工作量管理系统设计与实现

一、项目简介 随着高校信息化管理的发展&#xff0c;教师工作量管理成为教务系统中不可或缺的一部分。为此&#xff0c;我们设计并开发了一个基于 Spring Boot Vue 的教师工作量管理系统&#xff0c;系统结构清晰&#xff0c;功能完备&#xff0c;支持管理员和教师两个角色。…...

预先学习:构建智能系统的 “未雨绸缪” 之道

一、预先学习&#xff1a;训练阶段的 “模型预构建” 哲学 1.1 核心定义与生物启发 预先学习的本质是模拟人类的 “经验积累 - 快速决策” 机制&#xff1a;如同医生通过大量病例总结诊断规则&#xff0c;算法在训练阶段利用全量数据提炼规律&#xff0c;生成固化的 “决策模型…...

完善网络安全等级保护,企业需注意:

在数字化转型加速的当下&#xff0c;网络安全成为企业发展的基石。网络安全等级保护作为保障网络安全的重要举措&#xff0c;企业必须高度重视并积极落实。以下要点&#xff0c;企业在完善网络安全等级保护工作中需格外关注&#xff1a; 一、准确开展定级备案 企业首先要依据相…...

Trae 04.22版本深度解析:Agent能力升级与MCP市场对复杂任务执行的革新

我正在参加Trae「超级体验官」创意实践征文&#xff0c;本文所使用的 Trae 免费下载链接&#xff1a;Trae - AI 原生 IDE 目录 引言 一、Trae 04.22版本概览 二、统一对话体验的深度整合 2.1 Chat与Builder面板合并 2.2 统一对话的优势 三、上下文能力的显著增强 3.1 W…...

OceanBase 开发者大会:详解 Data × AI 战略,数据库一体化架构再升级

OceanBase 2025 开发者大会与5月17日在广州举行。这是继 4 月底 OceanBase CEO 杨冰宣布公司全面进入AI 时代后的首场技术盛会。会上&#xff0c;OceanBase CTO 杨传辉系统性地阐述了公司的 DataAI 战略&#xff0c;并发布了三大产品&#xff1a;PowerRAG、共享存储&#xff0c…...

正则表达式进阶(三):递归模式与条件匹配的艺术

在正则表达式的高级应用中&#xff0c;递归模式和条件匹配是处理复杂嵌套结构和动态模式的利器。它们突破了传统正则表达式的线性匹配局限&#xff0c;能够应对嵌套括号、HTML标签、上下文依赖等复杂场景。本文将详细介绍递归模式&#xff08;(?>...)、 (?R) 等&#xff0…...

ubuntu环境下 基于Python 打包的 批量命令行可视化操作工具 GUI

文章目录 一.需求&#xff1a;二.原理支撑&#xff1a;三.简单Demo四.封装成GUI1.依赖库2.代码 五.打包成可执行文件六.命令行的配置七.运行效果 一.需求&#xff1a; 作为测试工程师&#xff0c;为了到现场高效的调试&#xff0c;部署工作&#xff0c;需要一个可视化的工具&a…...

docker介绍与常用命令汇总

docker简介 docker是什么&#xff1f; Docker 是一个开源的应用容器引擎&#xff0c;它可以让开发者将应用与运行环境打包成一个标准的、可移植的容器&#xff08;Container&#xff09;&#xff0c;在任何地方都可以快速部署和运行&#xff0c;无需关心底层环境是否一致。 …...

[创业之路-369]:企业战略管理案例分析-9-战略制定-差距分析的案例之华为

一、综合案例 在战略制定中&#xff0c;华为通过差距分析明确战略方向&#xff0c;以应对市场挑战和实现长期发展目标。 以下为具体案例与分析&#xff1a; 1、案例背景 华为在通信设备领域崛起过程中&#xff0c;始终将差距分析作为战略制定的核心环节。面对国际竞争对手&…...