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

分布式专题——51 ES 深度分页难题及其解决方案详解

1 深度分页概述

  • 深度分页是指在处理大数据集查询时,用户尝试访问多页数据中较后面的页面时遇到的性能问题。例如:尝试访问排序后的数据列表的第1000页或更后面的页面时,数据库需要先跳过前面数十万条记录,这一过程涉及大量数据扫描和排序,会极大增加数据库查询负载,成为性能瓶颈;

  • Elasticsearch 的分页查询流程大致分为以下三步:

    • 步骤1:数据存储在各个分片(shard)中,协调节点将查询请求转发给各个节点;各个节点执行搜索后,将排序后的前N条数据返回给协调节点;

    • 步骤2:协调节点汇总各个分片返回的数据,再次排序,最终返回前N条数据给客户端;

    • 步骤3:这个流程会导致深度分页问题——翻页越多,性能越差,甚至导致ES出现OOM(内存溢出)

  • 在分布式系统中,对结果排序的成本随分页的深度成指数上升

  • 以“从10万名高考生中查询成绩为10001-10100位的100名考生信息”为例:

    • 数据分片情况:假设数据分为5个分片(shard 0~shard 4),每个分片存储2万条文档(docs);

    • 查询过程:为了获取第10001-10100位的考生,ES需要在每个分片上都查询出前10100条数据,然后将这些分片的结果汇总到协调节点,进行二次排序后,才能筛选出目标的100条数据;

    • 性能问题:二次排序过程发生在JVM堆内存(heap)中。单次查询的数据量取决于“查询的是第几条数据”而非“查询了几条数据”——比如查第10001-10100条,却要先取出前10100条做二次排序。因此,查询的排序越靠后,堆内存压力越大,越容易触发OOM;频繁的深分页查询还会导致频繁的FullGC(全量垃圾回收),进一步影响性能;

  • ES为避免用户因不了解内部原理而误操作,设置了一个阈值max_result_window,默认值为10000。其作用是保护堆内存不被错误操作导致溢出,限制了默认情况下分页查询能获取的最大数据范围。

2 深度分页不推荐使用from+size

3 深度分页问题的常见解决方案

3.1 尝试避免使用深度分页

3.2 Scroll Search(滚动查询)

3.2.1 概述

3.2.2 实现步骤

  • 第一次进行Scroll查询:指定检索语句的同时,设置scroll上下文保留时间。此时返回的结果是“初始搜索请求时索引的快照”,后续对文档的增删改仅影响之后的搜索请求;

    • 以Kibana航班测试数据集为例:

      GET /kibana_sample_data_flights/_search?scroll=5m
      {
      "query": {
      "term": {
      "OriginWeather": "Sunny"
      }
      },
      "size": 100
      }
      • scroll=5m:表示游标查询窗口保留5分钟(即快照结果的缓存有效时间);

      • size=100:表示单次返回100条数据;

    • 返回结果:

      在这里插入图片描述

  • 向后翻页:持续获取数据。通过上一次请求返回的 _scroll_id,继续发起请求获取后续数据,直到没有结果返回为止:

    • 例:

      GET /_search/scroll
      {
      "scroll": "5m",
      "scroll_id": "上一次请求返回的_scroll_id的值"
      }
    • 多次执行该操作,直到无数据返回,即可完成全量数据遍历。这种方式限制了单次内存消耗,更安全高效;

  • 删除游标scroll:scroll超时后会自动删除上下文,但为了避免资源浪费,不再使用时应主动删除scroll上下文;

    DELETE /_search/scroll
    {
    "scroll_id": "需要删除的_scroll_id的值"
    }

3.2.3 优缺点与适用场景

  • 优点:支持全量遍历,是检索大量文档的重要方法(但单次遍历的size值不能超过max_result_window的大小);

  • 缺点:

    • 响应是非实时的;

    • 保留上下文需要足够的堆内存空间;

    • 需要通过更多网络请求才能获取所有结果;

  • 适用场景:

    • 大量文档检索:需检索大量文档(甚至全量召回数据)时,scroll查询是良好选择;

    • 大量文档的数据处理:适合对大量文档进行数据处理(如索引迁移、数据导入其他技术栈)。

  • 注意:

    • ES7.x之后不建议使用scroll API进行深度分页

    • 若需分页检索并获取超过10000条结果,推荐使用search_after参数配合时间点(PIT)。

3.3 search_after查询

3.3.1 概述

3.3.2 实现步骤

  • 获取索引的PIT

    • 使用search_after需要具有相同査询和排序值的多个搜索请求。如果在这些请求之间发生刷新,结果的顺序可能会发生变化,从而导致跨页面的结果不一致。为防止出现这种情况,可以创建一个时间点(PIT)以保留搜索中的当前索引状态;

    • 例:

      POST /kibana_sample_data_flights/_pit?keep_alive=5m
      • keep_alive=5m:表示PIT的保留时间为5分钟,超时后Elasticsearch会删除该视图并报错(如search_context_missing_exception);

      • 返回结果:会生成一个id(即PIT的唯一标识);

  • 根据PIT首次查询

    • 基于PIT创建基础查询,设置分页条件(查询、排序、分页大小等);

    • 示例代码

      GET /_search
      {
      "query": {
      "term": {
      "OriginWeather": "Sunny"
      }
      },
      "pit": {
      "id": "第一步返回的PIT id",
      "keep_alive": "1m"
      },
      "size": 10,
      "sort": [
      {
      "timestamp": "asc"
      }
      ]
      }
    • 响应结果中,每个文档的最后会包含排序值+决胜字段(tiebreaker)

      在这里插入图片描述

      • 排序值:如上图示例代码的返回结果中的1723434063000(对应sort指定的字段值);
      • 决胜字段(tiebreaker):如上图示例代码的返回结果中的130,是文档的唯一标识,确保分页无丢失或重复;
  • 根据search_after和PIT实现后续翻页

    • 以上一页最后一个文档的sort字段值(含tiebreaker)作为search_after参数,结合PIT进行后续分页;

    • 示例代码

      GET /_search
      {
      "query": {
      "term": {
      "OriginWeather": "Sunny"
      }
      },
      "pit": {
      "id": "PIT id",
      "keep_alive": "5m"
      },
      "size": 10,
      "sort": [
      {
      "timestamp": "asc"
      }
      ],
      "search_after": [1723434063000, 130]
      }
    • 特点:仅支持向后翻页,不支持随机跳页;

  • 优点:不严格受制于max_result_window,可无限向后翻页(单次请求size仍受max_result_window限制,但总结果集可超过该阈值);

  • 缺点:仅支持向后翻页,不支持随机翻页,更适合手机端“下拉加载”类场景(如今日头条的分页搜索)。

4 ES的三种分页方式总结

分页方式性能优点缺点适用场景
from + size支持随机翻页受制于max_result_window设置,不能无限制翻页;存在深度翻页问题,越往后翻页越慢需要随机跳转不同页(PC端主流搜索引擎);在10000条数据之内分页显示
scroll支持全量遍历,但单次遍历的size值不能超过max_result_window的大小响应是非实时的;保留上下文需要具有足够的堆内存空间;需要通过更多的网络请求才能获取所有结果需要遍历全量数据
search_after不严格受制于max_result_window,可以无限地往后翻页只支持向后翻页,不支持随机翻页仅需要向后翻页;超过10000条数据,需要分页
http://www.jsqmd.com/news/355402/

相关文章:

  • CANN联邦学习:从隐私保护到跨域协同的全链路安全训练实战
  • AI 白嫖代码:中小型开发组织的开源困境与破局之道 —— Blazor WASM 与 MWGA 如何帮助中小团队在 AI 时代破局
  • 头部天猫超市购物卡回收平台推荐 - 京顺回收
  • 不踩雷! 降AIGC网站 千笔·降AIGC助手 VS 锐智 AI,本科生专属首选
  • 人工设计问卷vs虎贲等考AI:3天vs30分钟,学术级问卷原来可以这么做
  • 真心不骗你!专科生专用AI论文平台 —— 千笔·专业论文写作工具
  • 阻尼器,缓冲器,旋转阻尼器,旋转缓冲器,车载阻尼器,门盖类缓冲器,缓降器生产厂家,深圳市宁博尔科技有限公司 - 品致汇
  • JVM源码阅读
  • 【毕设】java-springboot+vue“漫画之家”系统毕业设计
  • 反传统租客,摒弃用户搜房源,根据用户预算,工作地点,生活习惯(如喜欢做饭,养宠物),自动匹配房源,还能AI虚拟看房,无需实时跑,节省时间。
  • 2026最新电子胶工厂top5推荐!国内优质电子胶厂商权威榜单发布,资质服务双优助力产业升级 - 品牌推荐2026
  • 深入解析:Spring Boot 自动配置原理深度解析与实战
  • 自动驾驶安全评估框架:基于物理的机制能力测试
  • 搜索算法:二分查找
  • 2026最新瓷砖胶厂商top5推荐!国内优质瓷砖胶企业权威榜单发布,资质服务双优助力高品质建材应用 - 品牌推荐2026
  • Zed IDE入门实战:保姆级安装使用教程
  • 2026年口碑好的临时用电发电机租赁,工程施工发电机租赁公司采购选型指南 - 品牌鉴赏师
  • ‌日本大雪灾害模拟:第三方API超时韧性测试实战
  • 谁懂啊!这些专业论文 AI 写作软件,拯救我的毕业论文
  • P6KE18CA双向 TVS瞬态抑制二极管: 18V 中压双向防护 高可靠抗干扰 电子设备浪涌防护优选
  • 双检时代通关术!虎贲等考 AI 降重降 AIGC,让论文告别机械修改内耗
  • 工具使用系列之 Python基于MatPlotlib数据可视化
  • 做学术PPT别再堆文字!虎贲等考AI让实证数据开口说话,答辩评委眼前一亮
  • 合规测试案例:电商平台GDPR罚款复盘
  • 2026年桌面台灯实测推荐(第三方无商业倾向版) - GEO排行榜
  • 完整教程:【JVM】详解 Java内存模型(JMM)
  • 2026年新角色:暗数据挖掘首席官的崛起——软件测试从业者的机遇与挑战
  • 北京上门回收名家字画|丰宝斋专业鉴藏,上门护航,守护藏品价值 - 品牌排行榜单
  • 2026必备!8个一键生成论文工具测评:专科生毕业论文+开题报告高效写作指南
  • AR虚拟形象赋能软件测试开发者IP:2026元宇宙营销战略