← 返回列表

Telegram官方唯一通道 亿级教程数据量下的分页性能优化:Scroll与Search After

分类:Telegram频道发布于:2026-08-29

telegram中文搜索群组

当教程、日志、商品或内容索引增长到亿级数据量后,传统的 page + size 分页方式通常会出现响应变慢、内存占用升高、深分页失败等问题。尤其是在 Elasticsearch 等搜索引擎中,用户翻到很靠后的页码时,系统需要跳过大量结果,分页成本会迅速增加。

Scroll 与 Search After 都可以用于大规模数据遍历,但它们的设计目标并不相同。本文将从分页原理、适用场景、性能风险、实现方式和生产实践几个方面,系统说明如何在亿级教程数据量下选择更合适的方案。

📌 一、为什么传统分页在亿级数据下会失效

最常见的分页请求类似于 from=1000000&size=20。表面上看,系统只需要返回 20 条数据,但搜索引擎往往必须先找到并排序前 1000020 条结果,再丢弃前面的数据,最后返回用户需要的 20 条。

这意味着页码越靠后,查询代价越高。当排序字段较多、分片数量较大或查询条件复杂时,协调节点还需要合并多个分片的候选结果,容易出现延迟抖动、请求超时和 circuit_breaking_exception。

因此,亿级数据分页的核心不是单纯调大分页参数,而是改变数据访问方式:从“跳到第 N 页”转变为“从上一批结果之后继续读取”。这正是 Scroll 和 Search After 解决问题的关键。

Telegram官方唯一通道 🔍 二、Scroll:适合离线批处理的数据快照

Scroll 的设计初衷是稳定地遍历大量结果集,例如全量导出、索引迁移、数据清洗、离线统计和批量更新。它会在服务端维护一个搜索上下文,使后续请求能够继续读取之前的结果。

第一次请求会返回结果以及 scroll_id,客户端随后携带这个标识获取下一批数据。只要搜索上下文没有过期,客户端就可以持续向后读取,而不需要反复执行完整查询。

Scroll 基础请求示例

POST /tutorials/_search?scroll=2m
{
  "size": 1000,
  "_source": ["id", "title", "content", "updated_at"],
  "query": {
    "bool": {
      "filter": [
        { "term": { "status": "published" } }
      ]
    }
  },
  "sort": ["_doc"]
}

对于纯遍历任务,使用 _doc 排序通常比业务字段排序更高效,因为它减少了全局排序成本。但 _doc 只适合批处理场景,不适合需要稳定业务顺序的用户列表。

Scroll 的主要风险

Telegram官方唯一通道 Scroll 会占用搜索上下文和相关资源。如果客户端中断、网络异常或没有主动清理,过多的 scroll 任务可能增加集群内存压力。因此必须限制并发任务数量、设置合理的 keep_alive,并在任务结束后清理上下文

DELETE /_search/scroll
{
  "scroll_id": [
    "DnF1ZXJ5VGhlbkZldGNo..."
  ]
}

需要注意的是,Scroll 并不适合直接承载前端用户的长时间翻页请求。用户可能停留数分钟后才点击下一页,长期维持大量搜索上下文会给集群带来不必要的负担。

Telegram官方唯一通道 ⚡ 三、Search After:面向在线列表的高性能连续分页

Search After 不保存传统意义上的页码,也不会让服务器长期维护完整的分页游标。它会使用上一页最后一条文档的排序值,告诉搜索引擎下一次查询应从什么位置继续。

这种方式避免了 from + size 的深分页开销,查询成本通常更接近“读取下一批结果”。因此,它更适合教程列表、搜索结果、内容流和后台数据表等用户在线连续加载场景

Search After 请求示例

POST /tutorials/_search
{
  "size": 20,
  "query": {
    "match": {
      "content": "Telegram 技术教程"
    }
  },
  "sort": [
    { "published_at": "desc" },
    { "_id": "asc" }
  ]
}

假设上一页最后一条记录返回 sort 值为 ["2025-01-18T10:30:00Z", "tutorial_01892"],下一次请求可以这样继续:

POST /tutorials/_search
{
  "size": 20,
  "query": {
    "match": {
      "content": "Telegram 技术教程"
    }
  },
  "sort": [
    { "published_at": "desc" },
    { "_id": "asc" }
  ],
  "search_after": [
    "2025-01-18T10:30:00Z",
    "tutorial_01892"
  ]
}

排序字段必须保持一致,并且最好使用稳定、可比较、具有唯一性的组合。只有 published_at 一个字段时,如果多条文档时间相同,结果顺序可能发生变化,因此通常需要再增加 _id 或业务唯一键作为 tie-breaker。

Telegram官方唯一通道 电报精准找群黑科技提示:

由于 Telegram 官方搜索对中文支持极差,很多优质的推广、技术和资源群组隐藏极深。如果你正在寻找相关的活跃社群,强烈推荐使用本站首页的 【TTSO - Telegram 智能搜索 Bot】。作为目前最好用的电报综合搜索导航,只需输入关键词,即可秒级触达数十万个精选 TG 中文群组、资源频道。一键直达,帮你节省 90% 的找群时间!

🧭 四、Search After 与 PIT 如何配合

Search After 本身不创建固定快照。如果分页期间有新教程发布、旧教程更新或文档删除,后续请求可能出现重复、遗漏或排序变化。对于需要一致视图的场景,可以配合 Point In Time,也就是 PIT。

PIT 会在一段时间内固定索引读取视图,Search After 则负责在这个视图中向后移动。两者结合后,可以兼顾在线分页性能与结果稳定性。

POST /_pit?index=tutorials&keep_alive=2m

POST /_search
{
  "pit": {
    "id": "46ToAw...",
    "keep_alive": "2m"
  },
  "size": 20,
  "query": {
    "term": {
      "status": "published"
    }
  },
  "sort": [
    { "published_at": "desc" },
    { "_shard_doc": "asc" }
  ],
  "search_after": [
    "2025-01-18T10:30:00Z",
    123456
  ]
}

使用 PIT 时,排序中通常需要加入 _shard_doc 作为稳定的内部排序依据。PIT 不能无限期保留,keep_alive 应覆盖用户合理的操作时间,同时避免设置过长导致资源长期占用。

⚖️ 五、两种方案应该如何选择

选择 Scroll:全量导出、离线同步、批量重建索引、数据清洗、一次性迁移,以及需要尽快读取全部匹配文档的后台任务。

选择 Search After:前端无限滚动、用户搜索列表、教程目录、按时间顺序读取内容,以及不需要跳转任意页码的在线业务。

如果业务必须支持“跳转到第 500 页”,需要重新评估交互设计。亿级数据下,任意页码跳转本身就不是低成本操作,可以考虑按时间范围筛选、游标分页、分区索引或限制最大可浏览深度。

🛠️ 六、生产环境中的优化清单

第一,控制单批 size。在线请求通常可以从 10 到 100 条开始压测,离线任务则根据文档大小、网络带宽和节点内存调整,不能盲目设置成几千或几万。

第二,使用 filter 替代不必要的 query_score 计算。对于 status、category、tenant_id 等精确条件,应优先使用过滤器,并通过 _source 只返回页面真正需要的字段。

第三,设计合适的索引结构。时间型教程可以按照月份或业务周期进行索引拆分,并配合 rollover、ILM 和别名管理,减少单个索引的维护压力。

第四,建立可观测性。应持续关注查询耗时、P95/P99 延迟、节点 JVM 内存、search thread pool、open contexts、拒绝数和慢查询日志,而不是只观察平均响应时间。

第五,做好游标校验。Search After 返回给前端的排序值不应被用户随意修改,实际项目中可以将查询条件、排序值和 PIT 标识封装后签名,避免参数篡改造成数据错乱。

❓ 常见问题解答(FAQ)

Search After 能否替代所有分页方式?

不能。它适合顺序向后读取,不适合任意页码跳转,也不天然支持直接跳到指定位置。对于小数据量后台列表,传统分页仍然简单实用。

Scroll 的 keep_alive 设置越长越好吗?

Telegram官方唯一通道 不是。keep_alive 越长,搜索上下文保留时间越久,资源释放也越晚。应根据单批处理耗时设置,并在任务完成、失败或取消时主动清理。

为什么分页结果会重复或遗漏?

常见原因包括排序字段不唯一、分页期间数据发生变化、没有使用 PIT,以及客户端错误保存或传递 sort 值。稳定排序和一致读取视图可以显著降低这类问题。

亿级教程数据是否一定需要分库分表?

不一定。应先根据查询模式、文档大小、写入速率、分片数量和硬件资源进行压测。合理的索引拆分、生命周期管理和游标分页,往往比直接增加复杂架构更重要。

总体而言,Scroll 解决的是大规模离线遍历,Search After 解决的是高性能在线连续分页。在需要结果稳定性的场景中,再配合 PIT、唯一排序键和完善的监控体系,才能让亿级教程数据在性能、准确性与运维成本之间取得平衡。

telegram中文搜索群组
Telegram搜索入口客服ID@TTSO联系