Elasticsearch(ES)分页

发布于:2025-06-29 ⋅ 阅读:(15) ⋅ 点赞:(0)

Elasticsearch(简称 ES)本身不适合传统意义上的“深分页”,但提供了多种分页方式,每种适用不同场景。我们来详细讲解:


一、基本分页(from + size)

最常用的分页方式,类似 SQL 的 LIMIT offset, size

查询语法示例:

GET /products/_search
{
  "query": {
    "match_all": {}
  },
  "from": 20,
  "size": 10
}

表示从第 21 条记录开始,取 10 条(第 3 页,每页 10 条)

优点:

  • 简单直观,适合前几页浏览。

缺点:

  • 深分页性能差:from 越大,ES 处理速度越慢,浪费内存和 CPU。
  • 默认最大 from + size10000(可修改 index.max_result_window

二、Scroll 分页(适合大批量导出)

Scroll 是一种游标查询,用于大量数据批量处理,如导出所有数据。

查询示例:

POST /products/_search?scroll=1m
{
  "size": 100,
  "query": {
    "match_all": {}
  }
}

响应返回:

{
  "_scroll_id": "...",
  "hits": {
    "hits": [ ... ]
  }
}

继续获取下一页:

POST /_search/scroll
{
  "scroll": "1m",
  "scroll_id": "..."
}

优点:

  • 适合全量导出、日志批处理等任务。
  • 内部避免重新排序,性能好。

缺点:

  • 不是实时的,不能跳页。
  • scroll 占内存,需要及时清除。

三、Search After(推荐用于深分页)

官方推荐用于实时系统中分页跳转到深页,无需使用 from

使用前提:

  • 必须排序
  • 每页记录中携带上页最后一条的排序字段值

示例:

第一页请求:

POST /products/_search
{
  "size": 10,
  "sort": [{ "price": "asc" }, { "_id": "asc" }]
}

返回结果中,拿到最后一条记录的排序值:

"sort": [100.0, "abc123"]

第二页请求使用 search_after

POST /products/_search
{
  "size": 10,
  "sort": [{ "price": "asc" }, { "_id": "asc" }],
  "search_after": [100.0, "abc123"]
}

优点:

  • 性能优于 from + size 的深分页
  • 可实时查询,稳定

缺点:

  • 不支持跳页(只能“下翻页”)
  • 前端不能直接点跳转页码(需记住前页的 sort 值)

四、Pit(Point in Time)+ Search After(ES 7.10+)

在使用 search_after 时,为避免分页期间数据变动带来的不一致问题,可以使用 PIT。

创建 PIT:

POST /products/_pit?keep_alive=1m

返回:

{
  "pit_id": "xxx"
}

查询:

POST /products/_search
{
  "size": 10,
  "pit": {
    "id": "xxx",
    "keep_alive": "1m"
  },
  "sort": [{ "price": "asc" }, { "_shard_doc": "asc" }],
  "search_after": [...]
}

各分页方式对比

方式 跳页支持 深分页性能 实时性 适合场景
from + size 首页、少量分页
scroll 导出/批处理
search_after ✅✅ 深分页、翻页
pit + search_after ✅✅✅ 实时且一致性强

实践建议

分页需求类型 建议用法
普通分页 from + size
超过1万条数据导出 scroll
深分页、实时查询 search_after + sort
高一致性深分页 pit + search_after


网站公告

今日签到

点亮在社区的每一天
去签到