ES 的四種分頁(yè)方式,如何選擇?
在 Elasticsearch 中,有 4種常見(jiàn)的分頁(yè)方法,這篇文章,我們將分析每種方法的優(yōu)缺點(diǎn)以及我們?cè)撊绾芜x擇。
1. 使用 from 和 size
使用 from 和 size是最常用的分頁(yè)方式,通過(guò)設(shè)置 from 參數(shù)指定從結(jié)果集的哪個(gè)位置開(kāi)始,size 參數(shù)指定返回多少條記錄。使用語(yǔ)法如下:
GET /index/_search
{
"from": 10,
"size": 10,
"query": {
"match": {
"field": "value"
}
}
優(yōu)點(diǎn):
- 簡(jiǎn)單易用:實(shí)現(xiàn)起來(lái)非常直觀,適用于大多數(shù)基本的分頁(yè)需求。
- 廣泛支持:Elasticsearch 搜索 API 默認(rèn)支持這種分頁(yè)方式。
缺點(diǎn):
- 性能問(wèn)題:對(duì)于深頁(yè)(高 from 值),性能會(huì)顯著下降,因?yàn)?Elasticsearch 需要跳過(guò)前面的 from 條記錄。這會(huì)導(dǎo)致查詢時(shí)間增加,尤其是當(dāng) from 值較大時(shí)。
- 資源消耗:高 from 值會(huì)消耗更多的內(nèi)存和CPU資源,可能影響集群性能。
適用場(chǎng)景:
- 淺分頁(yè):適用于前幾頁(yè)的查詢(例如,第1頁(yè)到第10頁(yè))。
- 小數(shù)據(jù)集:當(dāng)數(shù)據(jù)量較小且分頁(yè)需求不復(fù)雜時(shí)。
2. 使用 search_after
search_after基于排序值實(shí)現(xiàn)深度分頁(yè),通過(guò)提供上一個(gè)頁(yè)面的排序值來(lái)繼續(xù)檢索下一頁(yè)的數(shù)據(jù)。使用語(yǔ)法如下:
GET /index/_search
{
"size": 10,
"query": {
"match": {
"field": "value"
}
},
"sort": [
{ "timestamp": "asc" },
{ "_id": "asc" }
],
"search_after": [ "2023-01-01T00:00:00", "some_id" ]
}
優(yōu)點(diǎn):
- 高效深度分頁(yè):相比 from/size,search_after 在處理深層分頁(yè)時(shí)性能更好,不會(huì)隨著頁(yè)數(shù)增加而顯著下降。
- 去重性強(qiáng):結(jié)合唯一排序字段(如 _id),可以避免重復(fù)數(shù)據(jù)。
缺點(diǎn):
- 狀態(tài)管理:需要在客戶端保存上一次查詢返回的排序值,增加了實(shí)現(xiàn)復(fù)雜度。
- 不可跳頁(yè):無(wú)法像傳統(tǒng)分頁(yè)那樣直接跳轉(zhuǎn)到任意頁(yè),只能順序翻頁(yè)。
適用場(chǎng)景:
- 深度分頁(yè):適用于需要訪問(wèn)大量數(shù)據(jù)且需要高效性能的場(chǎng)景。
- 數(shù)據(jù)連續(xù)流:適合數(shù)據(jù)流式訪問(wèn),如日志檢索、實(shí)時(shí)數(shù)據(jù)分析等。
3. 使用 Scroll API
Scroll API適用于處理大量數(shù)據(jù)的批量檢索,通過(guò)保持一個(gè)在查詢時(shí)刻的快照,允許用戶遍歷整個(gè)結(jié)果集。使用語(yǔ)法如下:
POST /index/_search?scroll=1m
{
"size": 100,
"query": {
"match_all": {}
}
}
# 獲取后續(xù)數(shù)據(jù)
POST /_search/scroll
{
"scroll": "1m",
"scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAA..."
}
優(yōu)點(diǎn):
- 處理大量數(shù)據(jù):適合導(dǎo)出或批量處理大量數(shù)據(jù),性能穩(wěn)定。
- 避免跳頁(yè)問(wèn)題:通過(guò)持續(xù)的快照避免數(shù)據(jù)在檢索過(guò)程中變化影響結(jié)果。
缺點(diǎn):
- 資源消耗:保持 scroll 上下文會(huì)占用集群資源,尤其是在并發(fā)請(qǐng)求較高時(shí)。
- 不適合實(shí)時(shí)搜索:Scroll API 主要用于一次性檢索,不適合用戶交互的分頁(yè)需求。
適用場(chǎng)景:
- 批量數(shù)據(jù)導(dǎo)出:如數(shù)據(jù)遷移、備份等。
- 大規(guī)模分析:需要一次性處理大量文檔的場(chǎng)景。
4. 使用 Point in Time
使用 Point in Time (PIT)提供了一種基于時(shí)間點(diǎn)的查詢方式,允許在多個(gè)分頁(yè)請(qǐng)求中維持一致的視圖。使用語(yǔ)法如下:
POST /index/_search?pit=true&size=10
{
"sort": [...],
"query": { ... }
}
# 后續(xù)請(qǐng)求使用 pit_id
POST /index/_search
{
"pit": {
"id": "some_pit_id",
"keep_alive": "1m"
},
"sort": [...],
"query": { ... },
"search_after": [ ... ]
}
優(yōu)點(diǎn):
- 一致性視圖:在多個(gè)分頁(yè)請(qǐng)求中保持?jǐn)?shù)據(jù)的一致性,即使索引發(fā)生變化。
- 結(jié)合 search_after 使用:提高深度分頁(yè)的效率和一致性。
缺點(diǎn):
- 復(fù)雜度增加:需要管理 PIT 會(huì)話,包括生命周期和資源釋放。
- 資源消耗:維持 PIT 會(huì)話會(huì)占用集群資源。
適用場(chǎng)景:
- 需要一致性分頁(yè):如多用戶同時(shí)分頁(yè)瀏覽數(shù)據(jù),確保每個(gè)用戶看到的數(shù)據(jù)一致。
- 結(jié)合 search_after:需要高效的深度分頁(yè)且保持一致視圖的場(chǎng)景。
5. 如何選擇?
根據(jù)分頁(yè)深度選擇:
- 淺分頁(yè)(前幾頁(yè)):使用 from 和 size,實(shí)現(xiàn)簡(jiǎn)單且性能可接受。
- 深度分頁(yè):使用 search_after 或結(jié)合 Point in Time,提高性能并避免資源浪費(fèi)。
根據(jù)數(shù)據(jù)一致性要求:
- 無(wú)需嚴(yán)格一致性:from 和 size 已足夠,適用于數(shù)據(jù)不頻繁變動(dòng)的場(chǎng)景。
- 需要一致性視圖:使用 Point in Time,確保分頁(yè)過(guò)程中數(shù)據(jù)的一致性。
根據(jù)使用場(chǎng)景:
- 用戶交互分頁(yè):通常使用 from 和 size,適合大多數(shù) Web 應(yīng)用分頁(yè)需求。
- 批量處理或?qū)С觯菏褂?Scroll API,適合一次性處理大量數(shù)據(jù)的任務(wù)。
根據(jù)資源和性能考慮:
- 資源有限:避免使用 Scroll API,尤其是在高并發(fā)環(huán)境下。
- 性能優(yōu)化:對(duì)于頻繁的深度分頁(yè),search_after 和 Point in Time 是更優(yōu)的選擇。
6. 總結(jié)
本文,我們介紹了 ES的四種分頁(yè)方式:
- from 和 size:適用于淺分頁(yè),簡(jiǎn)單易用,但不適合深度分頁(yè)。
- search_after:適合深度分頁(yè),性能更優(yōu),但實(shí)現(xiàn)復(fù)雜度略高,且不支持隨機(jī)跳頁(yè)。
- Scroll API:適用于批量處理和導(dǎo)出,不適合實(shí)時(shí)用戶交互的分頁(yè)需求。
- Point in Time (PIT):提供一致的分頁(yè)視圖,適合需要數(shù)據(jù)一致性的深度分頁(yè)場(chǎng)景。
在實(shí)際開(kāi)發(fā)中,我們需要根據(jù)具體的業(yè)務(wù)需求、數(shù)據(jù)量、分頁(yè)深度和系統(tǒng)資源,選擇最合適的分頁(yè)方法,以達(dá)到最佳的性能和用戶體驗(yàn)。