Elasticsearch的Scroll操作
Scroll
Version:6.1
英文原文地址:Scroll
當一個搜索請求返回單頁結果時,可以使用 scroll API 檢索體積大量(甚至全部)結果,這和在傳統數據庫中使用游標的方式非常相似。
不要把?scroll?用于實時請求,它主要用于大數據量的場景。例如:將一個索引的內容索引到另一個不同配置的新索引中。
Client support for scrolling and reindexing
一些官方支持的客戶端提供了一些輔助類,可以協助滾動搜索和索引之間的文檔重索引:
Perl
? 參閱?Search::Elasticsearch::Client::5_0::Bulk?和?Search::Elasticsearch::Client::5_0::Scroll
Python
? 參閱?elasticsearch.helpers.*
NOTE:從 scroll 請求返回的結果反映了初始搜素請求生成時的索引狀態,就像時間快照一樣。對文檔的更改(索引、更新或者刪除)只會影響以后的搜索請求。
為了使用 scroll ,初始的搜索請求應該在查詢字符串中指定?scroll?參數,這個參數會告訴 Elasticsearch 將 “search context” 保存多久。例如:?scroll=1m
POST /twitter/tweet/_search?scroll=1m {"size": 100,"query": {"match" : {"title" : "elasticsearch"}} }上面的請求返回的結果里會包含一個?_scroll_id?,我們需要把這個值傳遞給?scroll?API ,用來取回下一批結果。
POST (1) /_search/scroll (2) {"scroll" : "1m", (3)"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==" (4) }(1)?GET?或者?POST?都可以
(2) URL 不能包含?index?和?type?名稱,原始請求中已經指定了
(3)?scroll?參數告訴 Elasticsearch 把搜索上下文再保持一分鐘
(4)?scroll_id?的值就是上一個請求中返回的?_scroll_id?的值
size?參數允許我們配置沒批結果返回的最大命中數。每次調用 scroll API 都會返回下一批結果,直到不再有可以返回的結果,即命中數組為空。
IMPORTANT:初始的搜索請求和每個 scroll 請求都會返回一個新的?_scroll_id?,只有最近的?_scroll_id?是可用的
NOTE:如果請求指定了過濾,就只有初始搜索的響應中包含聚合結果。
NOTE:Scroll 請求對?_doc?排序做了優化。如果要遍歷所有的文檔,而且不考慮順序,_doc?是最高效的選項。
GET /_search?scroll=1m {"sort": ["_doc"] }Keeping the search context alive
scroll?參數告訴了 Elasticsearch 應當保持搜索上下文多久。它的值不需要長到能夠處理完所有的數據,只要足夠處理前一批結果就行了。每個 scroll 請求都會設置一個新的過期時間。
通常,為了優化索引,后臺合并進程會把較小的段合并在一起創建出新的更大的段,此時會刪除較小的段。這個過程在 scrolling 期間會繼續進行,但是一個打開狀態的索引上下文可以防止舊段在仍需要使用時被刪除。這就解釋了 Elasticsearch 為什么能夠不考慮對文檔的后續修改,而返回初始搜索請求的結果。
TIP:使舊段保持活動狀態意味著需要更多的文件句柄。請確保你已將節點配置為擁有足夠的可用的文件句柄。詳情參閱?File Descriptors
你可以使用?nodes stats API?查看有多少搜索上下文處于開啟狀態
GET /_nodes/stats/indices/searchClear scroll API
當超出了?scroll timeout?時,搜索上下文會被自動刪除。但是,保持 scrolls 打開是有成本的,當不再使用 scroll 時應當使用?clear-scroll?API 進行顯式清除。
DELETE /_search/scroll {"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==" }可以使用數組傳遞多個 scroll ID
DELETE /_search/scroll {"scroll_id" : ["DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==","DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAABFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAAAxZrUllkUVlCa1NqNmRMaUhiQlZkMWFBAAAAAAAAAAIWa1JZZFFZQmtTajZkTGlIYkJWZDFhQQAAAAAAAAAFFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAABBZrUllkUVlCa1NqNmRMaUhiQlZkMWFB"] }使用?_all?參數清除所有的搜索上下文
DELETE /_search/scroll/_all也可以使用 query string 參數傳遞?scroll_id?,多個值使用英文逗號分割
DELETE /_search/scroll/DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==,DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAABFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAAAxZrUllkUVlCa1NqNmRMaUhiQlZkMWFBAAAAAAAAAAIWa1JZZFFZQmtTajZkTGlIYkJWZDFhQQAAAAAAAAAFFmtSWWRRWUJrU2o2ZExpSGJCVmQxYUEAAAAAAAAABBZrUllkUVlCa1NqNmRMaUhiQlZkMWFBSliced Scroll
如果 scroll 查詢返回的文檔數量過多,可以把它們拆分成多個切片以便獨立使用
GET /twitter/tweet/_search?scroll=1m {"slice": {"id": 0, (1)"max": 2 (2)},"query": {"match" : {"title" : "elasticsearch"}} } GET /twitter/tweet/_search?scroll=1m {"slice": {"id": 1,"max": 2},"query": {"match" : {"title" : "elasticsearch"}} }(1) 切片的 id
(2) 最大切片數量
上面的栗子,第一個請求返回的是第一個切片(id : 0)的文檔,第二個請求返回的是第二個切片的文檔。因為我們設置了最大切片數量是 2 ,所以兩個請求的結果等價于一次不切片的 scroll 查詢結果。默認情況下,先在第一個分片(shard)上做切分,然后使用以下公式:slice(doc) = floorMod(hashCode(doc._uid), max) 在每個 shard 上執行切分。例如,如果 shard 的數量是 2 ,并且用戶請求 4 slices ,那么 id 為 0 和 2 的 slice 會被分配給第一個 shard ,id 為 1 和 3 的 slice 會被分配給第二個 shard 。
每個 scroll 是獨立的,可以像任何 scroll 請求一樣進行并行處理。
NOTE:如果 slices 的數量比 shards 的數量大,第一次調用時,slice filter 的速度會非常慢。它的復雜度時 O(n) ,內存開銷等于每個 slice N 位,其中 N 時 shard 中的文檔總數。經過幾次調用后,篩選器會被緩存,后續的調用會更快。但是仍需要限制并行執行的 sliced 查詢的數量,以免內存激增。
為了完全避免此成本,可以使用另一個字段的?doc_values?來進行切片,但用戶必須確保該字段具有以下屬性:
- 該字段是數字類型
- 該字段啟用了?doc_values
- 每個文檔應當包含單個值。如果一份文檔有指定字段的多個值,則使用第一個值
- 每個文檔的值在創建文檔時設置了之后不再更新,這可以確保每個切片獲得確定的結果
- 字段的基數應當很高,這可以確保每個切片獲得的文檔數量大致相同
NOTE:默認情況下,每個 scroll 允許的最大切片數量時 1024。你可以更新索引設置中的?index.max_slices_per_scroll?來繞過此限制。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的Elasticsearch的Scroll操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Attention的梳理、随想与尝试
- 下一篇: Feature Tools:可自动构造机