這篇文章主要講解了“elasticsearch的ScanScroll如何使用”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“elasticsearch的ScanScroll如何使用”吧!
雙峰網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián)建站,雙峰網(wǎng)站設(shè)計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為雙峰數(shù)千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設(shè)要多少錢,請找那個售后服務(wù)好的雙峰做網(wǎng)站的公司定做!
ScanScroll 的特點
優(yōu)點
速度快
大數(shù)據(jù)量
缺點
不支持排序
不支持分頁
不支持評分
不支持續(xù)查
看起來,缺點要比優(yōu)點多很多,不過它很有用。如果說BULK是為了快速入庫存在的,那SCAN就是為了快速出庫而誕生的。ES的查詢性能優(yōu)越,但是分析能力弱。所以會有,比如把ES的數(shù)據(jù)拉到Hadoop集群去分析計算的需求,當然這個已經(jīng)有現(xiàn)成的插件了,不出所料也是用的SCAN。如果SCAN遭遇BULK, 也就是ES到ES的話,它有另一個更熟悉的名字叫 復(fù)制表。
def scanTest(): searchRes = es.search(index="users",size=10,body={"query": {"match_all": {}}},search_type="scan",scroll="10s") while True: scrollRes=es.scroll(scroll_id=searchRes["_scroll_id"],scroll="10s",ignore=[400, 404]) res_list = scrollRes["hits"]["hits"] if not len(res_list): break; for res in res_list: print res["_source"]["userName"]
整個流程比較清晰,先count一個總數(shù),下面每次scroll,返回size*分片數(shù)的數(shù)據(jù),直到遍歷全部。SCAN是支持查詢偏好preference的,可以指定分片,所以有人說的size*主分片數(shù),是不準確的,這個很容易驗證。
第一階段:Search
用TotalHitCountCollector統(tǒng)計下總數(shù),并且確定(節(jié)點,查詢上下文ID),Base64編碼成ScrollId返回
第二階段:SearchScroll
根據(jù)ScrollId去每個節(jié)點,找到查詢上下文ID執(zhí)行XFilteredQuery,收集結(jié)果,合并返回
第一階段除了返回總數(shù),還有一個很神秘的ScrollId,這個ScrollId長成這樣,很像Base64編碼過的。一定不是ID那么簡單,了解一番,果不其然 ,主要有3個部分組成type,context,attributes
type 分別是queryThenFetch,queryAndFetch,scan,我們這里講的是scan
attributes 只有一個元素,total_hits
context 是個分片的元組,有2個元素,分片 = [節(jié)點ID,查詢上下文ID]
ScrollId 是個很容易會暴露秘密的東西,我們會發(fā)現(xiàn)ScrollId 依賴的節(jié)點ID和查詢上下文ID都是變量,查詢上下文ID,每次請求都要遞增的。所以每次請求的ScrollId 都不一樣,導致了如果在我們的SCAN過程意外終止,我們可能需要重新來過。
每次SCAN,處理Scroll跳到下一頁去,我們自己指定form是無效的。
//SearchService private void processScroll(InternalScrollSearchRequest request, SearchContext context) { // process scroll context.from(context.from() + context.size()); context.scroll(request.scroll()); // ... }
//ScanContext public TopDocs execute(SearchContext context) throws IOException { ScanCollector collector = new ScanCollector(readerStates, context.from(), context.size(), context.trackScores()); Query query = new XFilteredQuery(context.query(), new ScanFilter(readerStates, collector)); try { context.searcher().search(query, collector); } catch (ScanCollector.StopCollectingException e) { // all is well } return collector.topDocs(); }
自定義的Filter,Collector,執(zhí)行搜索,收集那一頁的結(jié)果集
//ScanContext public void collect(int doc) throws IOException { if (counter >= from) { docs.add(new ScoreDoc(docBase + doc, trackScores ? scorer.score() : 0f)); } readerState.count++; counter++; if (counter >= to) { throw StopCollectingException; } }
根據(jù)以往數(shù)據(jù)庫的認識,count操作總是很慢的,這讓我很擔心會延長整個查詢的時間,后來我發(fā)現(xiàn)這種擔心是多余的,對于全文檢索count操作是很快速的。根據(jù)測試,17億數(shù)據(jù)24個分片,平均每個分片的count時間在200ms到700ms之間,最糟糕的情況下總數(shù)也能在1秒內(nèi)返回,這對于整個查詢時間而言是可以接受的。
感謝各位的閱讀,以上就是“elasticsearch的ScanScroll如何使用”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對elasticsearch的ScanScroll如何使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!