一、from + size 淺分頁 "淺"分頁可以理解為簡單意義上的分頁。 它的原理很簡單,就是查詢前20條數據,然後截斷前10條,只返回10-20的數據。這樣其實白白浪費了前10條的查詢。 GET test_dev/_search { "query": { "bool": { "filter": ...
一、from + size 淺分頁
"淺"分頁可以理解為簡單意義上的分頁。
它的原理很簡單,就是查詢前20條數據,然後截斷前10條,只返回10-20的數據。這樣其實白白浪費了前10條的查詢。
GET test_dev/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 10,
"from": 20,
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}
其中,from定義了目標數據的偏移值,size定義當前返回的數目。預設from為0,size為10,即所有的查詢預設僅僅返回前10條數據。
在這裡有必要瞭解一下from/size的原理:
因為es是基於分片的,假設有5個分片,from=100,size=10。則會根據排序規則從5個分片中各取回100條數據數據,然後彙總成500條數據後選擇最後面的10條數據。
做過測試,越往後的分頁,執行的效率越低。總體上會隨著from的增加,消耗時間也會增加。而且數據量越大,就越明顯!
二、scroll 深分頁
from+size查詢在10000-50000條數據(1000到5000頁)以內的時候還是可以的,但是如果數據過多的話,就會出現深分頁問題。
為瞭解決上面的問題,elasticsearch提出了一個scroll滾動的方式。
scroll 類似於sql中的cursor,使用scroll,每次只能獲取一頁的內容,然後會返回一個scroll_id
。根據返回的這個scroll_id
可以不斷地獲取下一頁的內容,所以scroll並不適用於有跳頁的情景。
GET test_dev/_search?scroll=5m
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 10,
"from": 0,
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}
scroll=5m
表示設置scroll_id
保留5分鐘可用。- 使用scroll必須要將from設置為0。
- size決定後面每次調用
_search
搜索返回的數量
然後我們可以通過數據返回的_scroll_id
讀取下一頁內容,每次請求將會讀取下10條數據,直到數據讀取完畢或者scroll_id
保留時間截止:
GET _search/scroll
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAJZ9Fnk1d......",
"scroll": "5m"
}
註意:請求的介面不再使用索引名了,而是 _search/scroll
,其中GET和POST方法都可以使用。
scroll刪除
根據官方文檔的說法,scroll的搜索上下文會在scroll的保留時間截止後自動清除,但是我們知道scroll是非常消耗資源的,所以一個建議就是當不需要了scroll數據的時候,儘可能快的把scroll_id
顯式刪除掉。
清除指定的scroll_id
:
DELETE _search/scroll/DnF1ZXJ5VGhlbkZldGNo.....
清除所有的scroll:
DELETE _search/scroll/_all
三、search_after 深分頁
scroll 的方式,官方的建議不用於實時的請求(一般用於數據導出),因為每一個 scroll_id
不僅會占用大量的資源,而且會生成歷史快照,對於數據的變更不會反映到快照上。
search_after
分頁的方式是根據上一頁的最後一條數據來確定下一頁的位置,同時在分頁請求的過程中,如果有索引數據的增刪改查,這些變更也會實時的反映到游標上。但是需要註意,因為每一頁的數據依賴於上一頁最後一條數據,所以無法跳頁請求。
為了找到每一頁最後一條數據,每個文檔必須有一個全局唯一值,官方推薦使用 _uid
作為全局唯一值,其實使用業務層的 id 也可以。
GET test_dev/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 20,
"from": 0,
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}
- 使用
search_after
必須要設置from=0
。 - 這裡我使用timestamp和
_id
作為唯一值排序。 - 我們在返回的最後一條數據里拿到sort屬性的值傳入到
search_after
。
使用sort返回的值搜索下一頁:
GET test_dev/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"age": 28
}
}
]
}
},
"size": 10,
"from": 0,
"search_after": [
1541495312521,
"d0xH6GYBBtbwbQSP0j1A"
],
"sort": [
{
"timestamp": {
"order": "desc"
},
"_id": {
"order": "desc"
}
}
]
}
你都學會了嗎?
版權聲明:本文為CSDN博主「zhexiao27」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/andybegin/article/details/83864171
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!