一 序
本文屬於極客時間Elasticsearch核心技術與實戰學習筆記系列。
二 分頁
2.1 From / Size
- 默認情況下,查詢按照相關度算分排序,返回前 10 條記錄
- 容易理解的分頁方案
- From : 開始位置
- Size:期望獲取文檔的總數
這裏理解下:我只需要查詢size條數據,而es則需要執行from+size條數據然後處理後返回。所以有很大的開銷。
2.2 分佈式系統中深度分頁的問題
ES 天生就是分佈式,查詢信息,但是數據分別保存在多個分片,多臺機器,ES 天生就需要滿足排序的需要(按照相關性算分)
當一個查詢:From = 990 ,Size =10
- 會在每個分片上先獲取 1000 個文檔。然後,通過 Coordinating Node 聚合所有結果。最後在通過排序選取前 1000 個文檔
- 頁數越深,佔用內容越多。爲了避免深度分頁帶來的內存開銷。ES 有個設定,默認限定到 10000 個文檔
2.3 demo
超出範圍,會報錯
3 Search After 避免深度分頁的問題
- 避免深度分頁的性能問題,可以實時獲取下一頁文檔信息
- 不支持指定頁數(From)
- 不能往下翻
- 第一步搜索需要指定 sort,並且保證值是唯一的(可以通過加入_id 保證唯一性)
- 然後使用上一次,最後一個文檔的 sort 值進行查詢
3.1 demo
數據準備:
#Scroll API
DELETE users
POST users/_doc
{"name":"user1","age":10}
POST users/_doc
{"name":"user2","age":11}
POST users/_doc
{"name":"user2","age":12}
POST users/_doc
{"name":"user2","age":13}
執行查詢
針對返回的結果wkD_8HIBYdMHFwfFArwf,放到search_after。這樣:
可以看到通過設置search_after的值,是可以避免深度分頁的。
3.2Search After 是如何解決深度分頁的問題
- 假設 Size 是 10
- 當查詢 990 -1000
- 通過唯一排序值定位,將每次要處理的文檔都控制在 10(避免性能開銷)
看到這裏,如果你熟悉MySQL,那麼 自然也會想到MySQL的分頁也可以採取類似的辦法來避免offset導致的分頁的尾頁慢。
4 Scoll API
- 創建一個快照,有新的數據寫入以後,無法被查找
- 每次查詢後,輸入上一次的 Scroll Id
4.1demo
數據準備,重新插入3條數據
我們使用scroll 生成快照,時間是5分鐘
再插入一條記錄:
吧第一次的scroll id拷出來,這樣執行查詢,最終只能查出3條記錄。
{
"_scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAABjfgWNURvOERhUl9RV2U4U2stczl1RmZFQQ==",
"took" : 5,
"timed_out" : false,
"terminated_early" : true,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [ ]
}
}
文檔4 是快照產生之後插入的,是無法被查到的。
5 不同的搜索類型和使用場景
Regular
- 需要實時獲取頂部的部分文檔。例如查詢最新的訂單
Scorll
- 需要全部文檔,例如導出全部數據
Pagination
- From 和 Size
- 如何需要深度分頁,則選用 Search After
***************************
理解很重要。