您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何解析ElasticSearch分頁方案,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
"淺"分頁是最簡單的分頁方案。es會根據查詢條件在每一個DataNode分片中取出from+size條文檔,然后在MasterNode中聚合、排序,再截取size-from的文檔返回給調用方。當頁數越靠后,也就是from+size越大,es需要讀取的數據也就是越大,聚合和排序的時候處理的數據量也越大,此時會加大服務器CPU和內存的消耗。
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的增加,消耗時間也會增加。而且數據量越大,就越明顯!
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
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" } } ] }
4:修改默認分頁限制值10000
可以使用下面的方式來改變ES默認深度分頁的index.max_result_window 最大窗口值
curl -XPUT http://127.0.0.1:9200/my_index/_settings -d '{ "index" : { "max_result_window" : 500000}}'
其中my_index為要修改的index名,500000為要調整的新的窗口數。將該窗口調整后,便可以解決無法獲取到10000條后數據的問題。
注意事項
通過上述的方式解決了我們的問題,但也引入了另一個需要我們注意的問題,窗口值調大了后,雖然請求到分頁的數據條數更多了,但它是用犧牲更多的服務器的內存、CPU資源來換取的。要考慮業務場景中過大的分頁請求,是否會造成集群服務的OutOfMemory問題。
修改最大限制值之后確實可以使from+size查詢到更后面頁的數據,但是每次查詢得到的總數量最大任然是10000,要想獲取大于1萬的查詢數據量,可以分兩步查詢,第一步使用scroll查詢獲取總數據量;第二部使用from+size查詢每頁的數據,并設置分頁。這樣即解決了from+size無法查詢10000之后的數據,也解決了scroll無法跳頁的問題。
使用scroll可能遇到的問題:
Caused by: org.elasticsearch.ElasticsearchException: Trying to create too many scroll contexts. Must be less than or equal to: [500]. This limit can be set by changing the [search.max_open_scroll_context] setting.
這個報錯是從es的日志文件中查出來的,大致意思是:嘗試創建更多的scroll對象失敗了,scroll對象總數量應該控制在500以內。可修改search.max_open_scroll_context的值來改變500這個閾值。
原因:通過scroll 深分頁可知道,es服務端會在內存中生成一個scroll_id對象,并會為該值指定過期時間,翻頁的時候使用scroll_id來獲取下一頁的數據。默認情況下,一個實例下面僅可以創建最多500個scroll上下文對象,也就是500個scroll_id。報此錯誤的原因就是創建scroll上下文對象失敗,因為當前已經存在500個這樣的對象了。
解決辦法:
1:通過觀察可以發現,即使不做任何的處理,過一會就又可以發起scroll請求了,這是因為時間超過了scroll生命周期時間,scroll對象自己死掉了一些。
2:按照提示說的,修改search.max_open_scroll_context的值
put http://{{es-host}}/_cluster/settings
{
"persistent": { "search.max_open_scroll_context": 5000 }, "transient": { "search.max_open_scroll_context": 5000 }
}
[圖片上傳失敗...(image-4dc354-1583253824871)]
image.png
3:在使用完scroll_id之后立即調用刪除接口,刪除該scroll對象
刪除單個scroll
DELETE http://{{es-host}}/_search/scroll
{
"scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAdsMqFmVkZTBJalJWUmp5UmI3V0FYc2lQbVEAAAAAAHbDKRZlZGUwSWpSVlJqeVJiN1dBWHNpUG1RAAAAAABpX2sWclBEekhiRVpSRktHWXFudnVaQ3dIQQAAAAAAaV9qFnJQRHpIYkVaUkZLR1lxbnZ1WkN3SEEAAAAAAGlfaRZyUER6SGJFWlJGS0dZcW52dVpDd0hB"
}
刪除所有scroll
delete http://{{es-host}}/_search/scroll/_all
上述內容就是如何解析ElasticSearch分頁方案,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。