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 + size
為 10000(可修改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 |