前言
這是我在這個(gè)網(wǎng)站整理的筆記,有錯(cuò)誤的地方請(qǐng)指出,關(guān)注我,接下來(lái)還會(huì)持續(xù)更新。
作者:神的孩子都在歌唱
一. 簡(jiǎn)介
search_after
是 Elasticsearch 提供的一種分頁(yè)查詢(xún)方式,它可以用來(lái)在已經(jīng)排序的結(jié)果集中進(jìn)行分頁(yè)查詢(xún)。
search_after查詢(xún)步驟如下(下面有具體的例子幫助理解):
最后一條排序結(jié)果相當(dāng)于它的游標(biāo)
優(yōu)點(diǎn):
-
性能優(yōu)勢(shì): 相對(duì)于傳統(tǒng)的
from
和size
參數(shù)來(lái)說(shuō),search_after
在處理大量數(shù)據(jù)時(shí)性能更好,因?yàn)樗恍枰^(guò)之前的結(jié)果集,不嚴(yán)格受制于 max_result_window,可以無(wú)限制往后翻頁(yè)。from
和size
只能翻頁(yè)10000條. -
適用于實(shí)時(shí)數(shù)據(jù): 在實(shí)時(shí)數(shù)據(jù)更新頻繁的場(chǎng)景下,
search_after
可以確保查詢(xún)結(jié)果的準(zhǔn)確性,因?yàn)樗粫?huì)受到新數(shù)據(jù)插入的影響。 -
避免深度分頁(yè)問(wèn)題: 使用
search_after
可以避免深度分頁(yè)問(wèn)題,即當(dāng)頁(yè)數(shù)很大時(shí),傳統(tǒng)的分頁(yè)方式性能會(huì)下降。
缺點(diǎn):
-
需要結(jié)果排序: 使用
search_after
前需要對(duì)結(jié)果集進(jìn)行排序,如果排序字段較多或者數(shù)據(jù)量較大,可能會(huì)影響性能。 -
只適用于唯一排序字段:
search_after
只支持基于唯一排序字段的分頁(yè)查詢(xún),如果有多個(gè)排序字段,需要確保排序字段的唯一性。 -
不支持隨機(jī)訪問(wèn): 由于
search_after
是基于上一頁(yè)的最后一個(gè)文檔進(jìn)行分頁(yè),所以不支持隨機(jī)訪問(wèn),只能逐頁(yè)查詢(xún)。
使用場(chǎng)景:
-
大數(shù)據(jù)量分頁(yè)查詢(xún): 當(dāng)需要處理大量數(shù)據(jù)并進(jìn)行分頁(yè)查詢(xún)時(shí),
search_after
可以提供更好的性能。 -
實(shí)時(shí)數(shù)據(jù)展示: 在實(shí)時(shí)數(shù)據(jù)展示的場(chǎng)景下,可以使用
search_after
來(lái)確保查詢(xún)結(jié)果的準(zhǔn)確性。 -
避免深度分頁(yè)問(wèn)題: 當(dāng)需要避免深度分頁(yè)問(wèn)題時(shí),可以考慮使用
search_after
來(lái)提高查詢(xún)效率。
官方文檔說(shuō)明不再建議使用scroll滾動(dòng)分頁(yè)和from size分頁(yè),建議使用search_after
We no longer recommend using the scroll API for deep pagination. If you need to preserve the index state while paging through more than 10,000 hits, use the search_after parameter with a point in time (PIT).
我們不再建議使用滾動(dòng) API 進(jìn)行深度分頁(yè)。如果需要在分頁(yè)超過(guò) 10,000 個(gè)命中時(shí)保留索引狀態(tài),請(qǐng)使用帶有時(shí)間點(diǎn) (PIT) 的 search_after 參數(shù)。
By default, you cannot use
from
andsize
to page through more than 10,000 hits. This limit is a safeguard set by theindex.max_result_window
index setting. If you need to page through more than 10,000 hits, use thesearch_after
parameter instead.默認(rèn)情況下,您不能使用
from
和size
翻閱超過(guò) 10,000 個(gè)點(diǎn)擊。該限制是由索引設(shè)置設(shè)置的保障措施index.max_result_window
。如果您需要翻閱超過(guò) 10,000 個(gè)點(diǎn)擊,請(qǐng)使用search_after
參數(shù)代替。
二. 不帶PIT的search_after查詢(xún)
建議帶PIT,我舉的這個(gè)列子是幫助理解PIT的作用
2.1 構(gòu)造數(shù)據(jù)
PUT /test/_bulk?refresh
{"index":{}}
{"name": "小狗", "leg": 4, "iswing": false}
{"index":{}}
{"name": "小雞", "leg": 2, "iswing": true}
{"index":{}}
{"name": "小貓", "leg": 4, "iswing": false}
2.2 search_after分頁(yè)查詢(xún)
注意:當(dāng)我們使用search_after時(shí),from值必須設(shè)置為0或者-1。
首先我們通過(guò)排序查詢(xún)10條數(shù)據(jù)
GET /test/_search
{
"size": 10,
"sort": [
{
"name.keyword": {
"order": "desc" // 對(duì)返回的值進(jìn)行排序
}
}
]
}
要獲取下一頁(yè)結(jié)果,需要使用最后一條文檔的排序值(也就是sort列表里面的值) 作為 search_after 參數(shù)重新運(yùn)行上一個(gè)搜索。
GET test/_search
{
"size": 10,
"search_after": ["小雞"],
"sort": [
{
"name.keyword": {
"order": "desc"
}
}
]
}
這樣子他就會(huì)從排序好的name為小貓開(kāi)始查詢(xún)
2.2 問(wèn)題
每次檢索新的結(jié)果頁(yè)時(shí)更新數(shù)組,重復(fù)此過(guò)程。如果這些請(qǐng)求之間發(fā)生刷新,結(jié)果的順序可能會(huì)發(fā)生變化,從而導(dǎo)致頁(yè)面之間的結(jié)果不一致。為了防止這種情況,您可以創(chuàng)建一個(gè)時(shí)間點(diǎn) (PIT) 來(lái)在搜索中保留當(dāng)前索引狀態(tài)。
排序的值不唯一,翻頁(yè)的時(shí)候文檔對(duì)應(yīng)不上。為了防止這種情況,PIT 搜索請(qǐng)求都會(huì)添加一個(gè)名為 _shard_doc 的隱式排序字段,該字段也可以顯式提供,這個(gè)字段在es中叫做 tiebreaker 。此字段包含每個(gè)文檔的唯一值。如果您不包含tiebreaker字段,則分頁(yè)結(jié)果可能會(huì)丟失或重復(fù)命中。
比如我在插入一只小鳥(niǎo)
PUT /test/_bulk?refresh
{"index":{}}
{"name": "小鳥(niǎo)", "leg": 2, "iswing": true}
在執(zhí)行查詢(xún)語(yǔ)句
GET test/_search
{
"size": 10,
"search_after": ["小雞"],
"sort": [
{
"name.keyword": {
"order": "desc"
}
}
]
}
可以看到查詢(xún)的結(jié)果發(fā)生了變化,并且第11條應(yīng)該還是小雞而不是小鳥(niǎo)
為了解決這種情況,es在7.x引入了PIT的概念,它相當(dāng)于是 存儲(chǔ)索引數(shù)據(jù)狀態(tài)的輕量級(jí)視圖。
三. 帶PIT的search_after查詢(xún)
一些關(guān)于PIT的知識(shí):
PIT的快照時(shí)間點(diǎn): 創(chuàng)建 PIT 時(shí)記錄的是索引狀態(tài)的快照,而不是實(shí)時(shí)數(shù)據(jù)。即使 PIT 不過(guò)期,它也只反映創(chuàng)建 PIT 時(shí)的索引狀態(tài),而不包括之后新增的數(shù)據(jù)。
數(shù)據(jù)更新延遲: 即使使用 PIT 進(jìn)行查詢(xún),由于數(shù)據(jù)寫(xiě)入和索引過(guò)程中可能存在一定的延遲,新數(shù)據(jù)可能不會(huì)立即反映在查詢(xún)結(jié)果中。這種延遲可能導(dǎo)致查詢(xún)結(jié)果不是實(shí)時(shí)的。
實(shí)時(shí)性需求: 如果需要實(shí)時(shí)性較高的查詢(xún)結(jié)果,可能需要結(jié)合其他機(jī)制或策略來(lái)確保數(shù)據(jù)的實(shí)時(shí)性,如定時(shí)刷新 PIT、定時(shí)重新創(chuàng)建 PIT 等。
PIT對(duì)于翻頁(yè)的作用:PIT確保了在后續(xù)翻頁(yè)的過(guò)程中,可能會(huì)有新數(shù)據(jù)寫(xiě)入等操作,但這些操作不會(huì)對(duì)原有結(jié)果集構(gòu)成影響,保障數(shù)據(jù)的一致性。
關(guān)于 pit的官方文檔
3.1 構(gòu)建第一次查詢(xún)條件
POST /test/_pit?keep_alive=1m
keep_alive必須要加上,它表示這個(gè)pit能存在多久,這里設(shè)置的是1分鐘
構(gòu)建第一次查詢(xún)條件
GET /_search
{
"size": 10,
"pit": {
"id": "z9_qAwELdGVzdC0wMDAwMDQWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAWWGlMYTRUQ2VUaE9PVlJHNzRTdHBVdwAAAAAAAAauuRZ3bEkwVkx1MlR6YVlsMUZ4MHpUV05nAAEWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAA",
"keep_alive":"1m"
},
"sort": [
{
"name.keyword": {
"order": "desc"
}
}
]
}
輸出值如下
我上面展示的是最后一條文檔,可以看到排序sort中莫名多了個(gè)28 ,這在es官方文檔中叫做tiebreaker ,官方文檔中解釋如下
如果您使用 PIT,tiebreaker 是 隱含的排序值,是基于_shard_doc 的升序排序方式。 _shard_doc 值是 PIT 中的分片索引和 Lucene 的內(nèi)部文檔 ID 的組合,它對(duì)于每個(gè)文檔都是唯一的 。您還可以在搜索請(qǐng)求中手動(dòng)添加 tiebreaker 以自定義順序:
網(wǎng)上解釋:tiebreaker (決勝字段),tiebreaker 等價(jià)于_shard_doc。tiebreaker 本質(zhì)是每個(gè)文檔的唯一值,確保分頁(yè)不會(huì)丟失或者分頁(yè)結(jié)果數(shù)據(jù)出現(xiàn)重復(fù)(相同頁(yè)重復(fù)或跨頁(yè)重復(fù))。
可以在sort里面加上_shard_doc 進(jìn)行自定義排序
"sort": [
{
"name.keyword": {
"order": "desc"
},
"_shard_doc": "asc"
}
3.2 進(jìn)行下一頁(yè)查詢(xún)
我們?cè)谀盟黶ort里面的值放入到search_after中進(jìn)行下一頁(yè)查詢(xún)
在每個(gè)搜索請(qǐng)求中添加 keep_alive 參數(shù)來(lái)延長(zhǎng) PIT 的保留期,相當(dāng)于是重置了一下時(shí)間
GET /_search
{
"size": 10,
"pit": {
"id": "z9_qAwELdGVzdC0wMDAwMDQWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAWWGlMYTRUQ2VUaE9PVlJHNzRTdHBVdwAAAAAAAAauuRZ3bEkwVkx1MlR6YVlsMUZ4MHpUV05nAAEWVGxjUUVIUzhRQktTTkJRU3VQQXlodwAA",
"keep_alive":"1m"
},
"sort": [
{
"name.keyword": {
"order": "desc"
}
}
],
"search_after": [
"小雞",
28
],
"track_total_hits": false // 禁用總點(diǎn)擊率跟蹤以加快分頁(yè)速度
}
通過(guò)以下輸出可以看到。我們已經(jīng)成功進(jìn)入到下一頁(yè)了
這樣子就能夠成功進(jìn)行分頁(yè)查詢(xún)了
3.3 刪除PIT
完成后,您應(yīng)該刪除您的 PIT。
DELETE /_pit
{
"id" : "46ToAwMDaWR5BXV1aWQyKwZub2RlXzMAAAAAAAAAACoBYwADaWR4BXV1aWQxAgZub2RlXzEAAAAAAAAAAAEBYQADaWR5BXV1aWQyKgZub2RlXzIAAAAAAAAAAAwBYgACBXV1aWQyAAAFdXVpZDEAAQltYXRjaF9hbGw_gAAAAA=="
}
四.參考文章
https://blog.csdn.net/qq_26857259/article/details/134372438
https://blog.csdn.net/yangbindxj/article/details/123979413 有上一頁(yè)方案文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-847595.html
作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
轉(zhuǎn)載說(shuō)明:務(wù)必注明來(lái)源,附帶本人博客連接。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-847595.html
到了這里,關(guān)于elasticsearch 深度分頁(yè)查詢(xún) Search_after(圖文教程)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!