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

一次解决 Elasticsearch 两大难题: 掌握去重和深分页的最佳实践

文章目录

  • 省流:ES去重取最新+分页
      • `from` + `size` + `collapse`
      • `search_after` + `collapse`
      • `composite`
  • 📢废话版:经历和踩坑
    • 🎬前言
    • 🧐事情并不简单
    • 🙃无可奈何的决定
    • 🤯坑那坑那
        • 坑 1:最大`1w`条数据限制
        • 坑 2:深分页的性能陷阱
          • 解决方案:`search_after` 和 `scroll`
        • **坑 3:分页与去重的爱恨情仇**
      • 💭总结

省流:ES去重取最新+分页

from + size + collapse

GET users/_search
{"size": 2,"from": 0, // collapse去重"collapse": {"field": "csin",//将重复数据排序取最新的一条"inner_hits": {//需要获取最新数据的doc"name": "latest_doc","size": 1,"sort": [{"valDate": {"order": "desc"}}]}}
}
  • 优点:
    • 简单易用,无需额外逻辑
  • 缺点:
    • 执行进行浅分页,超过1w条数据后报错
    • 仅支持单字段去重

search_after + collapse

GET users/_search
{"size": 2,//需要排序,根据该字段进行翻页"sort": [{"csin": {"order": "asc"}}],//查询起点"search_after": ["CSIN-18190"],"collapse": {"field": "csin","inner_hits": {//需要获取最新数据的doc"name": "latest_doc","size": 1,"sort": [{"valDate": {"order": "desc"}}]}}
}
  • 优点:

    • 性能优异:search_after 避免了传统分页的性能陷阱
  • 缺点:

    • 仅支持单字段去重:collapse 只能基于一个字段进行去重

    • 不能聚合:无法对去重后的结果进行聚合操作

composite

GET /users/_search
{"size": 0,//通过csin进行分组"aggs": {"by_csin": {"composite": {"size": 10,"sources": [{"csin_field": {"terms": {"field": "csin"}}}],//分页"after": {"csin_field": "CSIN-18190"}},//取最新1"aggs": {"latest_doc": {"top_hits": {"size": 1,"sort": [{"valDate": {"order": "asc"}}]}}}}}
}
  • 优点:

    • 最强分页:专为聚合结果分页设计,非常稳定高效

    • 支持多字段去重:composite 可以同时对多个字段进行去重

  • 缺点:

    • 内存开销大:聚合操作通常比 collapse 更耗费内存。
方案去重方式分页方式聚合支持多字段去重性能适用场景主要缺点
from + size + collapse单字段折叠去重浅分页中等小数据量,简单查询超过 1w 条报错,无法深分页
search_after + collapse单字段折叠去重深分页(游标)大数据量分页去重仅支持单字段去重,无法聚合
composite 聚合多字段去重聚合分页(after 游标)中等偏低大数据量、多字段去重、聚合计算内存消耗大,操作复杂,排序方向需注意

📢废话版:经历和踩坑

🎬前言

    最近手上接到了一个新的需求,要求从A表抽数据到B表,给前端展示用。听到这个需求:心头一乐,这不是就是ETL吗?写个简单的查询插入即可,简单!!!

在这里插入图片描述


🧐事情并不简单

    三下五除二写完代码之后,自信满满的点下了运行按钮,接下来只需要抖腿等结果就行了。时间就这样一分一秒的过去:一分钟,五分钟,十分钟。。。还没有执行完,更准确的说,是还有查询完,更别说插入了。我心里咯噔一下,暗叹不妙。这个表的数据看来不少。。。。

    怀着验证的心去查了下表,好好好,连count都出不来结果,看这架势,数据量至少得破亿。顺便看了下表结构,这么大的数据量,竟然连分区都没有。这不慢才怪哩

在这里插入图片描述

    在求爷爷告奶奶的求教一番过后,一个老兄跟我说,ES 上面也有备份,可以去那上面看看。。。不得不说,ES 就是快,在 ES 执行了下count,基本是秒出结果,数据量有2亿!!!还是成增长态势。。。


🙃无可奈何的决定

    就现在的情形,在数据库没做任何处理的情况下,一个count都执行了十几分钟,指望数据库去做加工,那不成了厕所点灯——找死吗?这。。似乎也没得选,只能放弃数据库,拥抱 ES,虽然 ES 并非传统关系型数据库,本身并不适合做这类工作,但是他起码出的来结果啊。。。


🤯坑那坑那

    在尝试 ES 的过程中并不是一帆风顺,原本在数据库中一条select搞定的事,在 ES 会变成好几条。。。

在这里插入图片描述

坑 1:最大1w条数据限制

    本着知之然,知其所以然的态度,去探究了下 ES 为什么会有这个反人类的限制?发现原因其实很简单,当查询结果超过1w条时,ES 认为你可能在进行一个 全量扫描 操作,而这种操作通常会消耗巨大的内存和 CPU 资源,可能导致集群崩溃。为了保护集群,它在默认情况下直接报错,拒绝执行。果然快是有代价的

    为了绕开这个限制,就不能再使用传统的 fromsize 分页方式,而是需要采用 深分页 的方案


坑 2:深分页的性能陷阱

    解决1w条限制最简单的方式就是不让他限制,即通过设置 index.max_result_window解决,但是fromsize 依然是深分页的性能黑洞

    比如,想获取第10001页、每页10条数据时,ES 必须在每个分片上处理前100010条文档,然后将它们全部发送到协调节点进行合并排序。这导致:

  • 内存爆炸:协调节点需要将海量数据加载到内存中进行排序
  • 网络风暴:分片之间传输的数据量呈线性增长

这种方式的性能瓶颈在于,它 无法跳过前面的数据,每次查询都必须从头开始计算

解决方案:search_afterscroll

    问题虽然存在,但并不是没有解决方案,ES 提供了两个更高效的方案:

  1. search_after (推荐):一种基于 游标 的分页方式。它通过上一个结果的排序值,来确定下一个查询的起点。它无状态、性能高,是实现无限翻页的最佳选择

  2. scroll (不推荐):会创建一个 时间点快照,让你能够遍历整个结果集。但它资源消耗大,且不能进行实时查询,通常只用于 全量数据导出


坑 3:分页与去重的爱恨情仇

    当需求升级为“分页”+“去重”时,事情变得更复杂。例如,要按商品ID 去重,并返回每个ID下最新的商品。这时,会发现简单的 search_after 也不够用了。解决方案需要同时运用collapsecomposite 聚合这两种高级武器了

  • collapse:用于在搜索结果返回之前,根据某个字段将文档折叠去重。它性能高,配合 search_after 能完美实现高效的去重分页。
  • composite 聚合:如果你需要对去重后的数据进行聚合计算,比如计算每个去重组的总和,那么 composite 聚合是唯一的选择。它专为聚合结果分页而设计

    至于怎么解决的,方案已经放在文章开头了,这里就不过多的赘述了。。。

💭总结

    使用 ES 的过程中不可谓不艰难,第一次使用就遇到了这么个需求,时也命也?不过,这也加深了我对 ES 的理解,不知道大伙儿在用 ES 的过程中有遇到哪些坑呢~~

http://www.xdnf.cn/news/1411579.html

相关文章:

  • Day19_【机器学习—线性回归 (1)】
  • PerfectSquares.java
  • c++程序员日常超实用工具(长期记录更新)
  • 疯狂星期四文案网第56天运营日记
  • 创意无界:云渲染如何让视觉创作触手可及
  • python如何下载svg图片
  • 【LeetCode - 每日1题】解数独
  • 虚幻引擎技术开放日!facecar分享3D HMI设计与UE开发经验
  • 基于单片机智能电子秤/称重计费
  • Idea启动错误-java.lang.OutOfMemoryError:内存不足错误。
  • DBeaverEE Mac 数据库管理工具
  • 决胜千里之外:服务器及硬件项目标书制作全流程与避坑指南
  • 《SVA断言系统学习之路》【02】并发断言
  • leetcode解题思路分析(一百六十六)1438 - 1444 题
  • 【机器学习基础】无监督学习算法的现代演进:从数据探索到智能系统的自主发现能力
  • 深入理解Nginx反向代理及其应用
  • 京东商品评论接口技术实现:从接口分析到数据挖掘全方案
  • 【Android】Notification 的基本使用
  • [线上问题排查]深度剖析:一条MySQL慢查询的全面优化实战
  • Cesium 入门教程(十四):鼠标键盘交互
  • 设置Ubuntu 22.04 LTS上的rsync同步服务
  • 提取动漫图像轮廓并拟合为样条曲线(MATLAB)
  • WEB漏洞挖掘篇(一) 基本概念、十大常見WEB漏洞
  • Python训练营打卡Day49-神经网络调参指南
  • 赵玉平《刘备谋略》读书笔记(上部)
  • 如何通过 AI IDE 集成开发工具快速生成简易留言板系统
  • 链表OJ做题报告
  • 批量修改用户密码的命令chpasswd
  • 使用组合子构建抽象语法树
  • vsgCs显示谷歌全球倾斜模型-数据转换