關於我,
邯鄲人。
對這類話題感興趣?歡迎發送郵件至
donlianli@126.com;或者關注我的微信公眾號“猿界汪汪隊”
es在查詢時,可以指定搜索類型為QUERY_THEN_FETCH,QUERY_AND_FEATCH,DFS_QUERY_THEN_FEATCH和DFS_QUERY_AND_FEATCH。那么這4種搜索類型有什么區別?
分布式搜索背景介紹:
ES天生就是為分布式而生,但分布式有分布式的缺點。比如要搜索某個單詞,但是數據卻分別在5個分片(Shard)上面,這5個分片可能在5台主機上面。因為全文搜索天生就要排序(按照匹配度進行排名),但數據卻在5個分片上,如何得到最后正確的排序呢?ES是這樣做的,大概分兩步。
step1、ES客戶端會將這個搜索詞同時向5個分片發起搜索請求,這叫Scatter,
step2、這5個分片基於本Shard獨立完成搜索,然后將符合條件的結果全部返回,這一步叫Gather。
客戶端將返回的結果進行重新排序和排名,最后返回給用戶。也就是說,ES的一次搜索,是一次scatter/gather過程(這個跟mapreduce也很類似).
然而這其中有兩個問題。
第一、數量問題。比如,用戶需要搜索"雙黃連",要求返回最符合條件的前10條。但在5個分片中,可能都存儲着雙黃連相關的數據。所以ES會向這5個分片都發出查詢請求,並且要求每個分片都返回符合條件的10條記錄。當ES得到返回的結果后,進行整體排序,然后取最符合條件的前10條返給用戶。這種情況,ES5個shard最多會收到10*5=50條記錄,這樣返回給用戶的結果數量會多於用戶請求的數量。
第二、排名問題。上面搜索,每個分片計算分值都是基於自己的分片數據進行計算的。計算分值使用的詞頻率和其他信息都是基於自己的分片進行的,而ES進行整體排名是基於每個分片計算后的分值進行排序的,這就可能會導致排名不准確的問題。如果我們想更精確的控制排序,應該先將計算排序和排名相關的信息(詞頻率等)從5個分片收集上來,進行統一計算,然后使用整體的詞頻率去每個分片進行查詢。
這兩個問題,估計ES也沒有什么較好的解決方法,最終把選擇的權利交給用戶,方法就是在搜索的時候指定query type。
1、query and fetch
向索引的所有分片(shard)都發出查詢請求,各分片返回的時候把元素文檔(document)和計算后的排名信息一起返回。這種搜索方式是最快的。因為相比下面的幾種搜索方式,這種查詢方法只需要去shard查詢一次。但是各個shard返回的結果的數量之和可能是用戶要求的size的n倍。
2、query then fetch(默認的搜索方式)
如果你搜索時,沒有指定搜索方式,就是使用的這種搜索方式。這種搜索方式,大概分兩個步驟,第一步,先向所有的shard發出請求,各分片只返回排序和排名相關的信息(注意,不包括文檔document),然后按照各分片返回的分數進行重新排序和排名,取前size個文檔。然后進行第二步,去相關的shard取document。這種方式返回的document與用戶要求的size是相等的。
3、DFS query and fetch
這種方式比第一種方式多了一個初始化散發(initial scatter)步驟,有這一步,據說可以更精確控制搜索打分和排名。
4、
DFS
query then fetch
比第2種方式多了一個初始化散發(initial scatter)步驟。
DSF是什么縮寫?初始化散發是一個什么樣的過程?
從es的官方網站我們可以指定,初始化散發其實就是在進行真正的查詢之前,先把各個分片的詞頻率和文檔頻率收集一下,然后進行詞搜索的時候,各分片依據全局的詞頻率和文檔頻率進行搜索和排名。顯然如果使用DFS_QUERY_THEN_FETCH這種查詢方式,效率是最低的,因為一個搜索,可能要請求3次分片。但,使用DFS方法,搜索精度應該是最高的。
至於DFS是什么縮寫,沒有找到相關資料,這個D可能是Distributed,F可能是frequency的縮寫,至於S可能是Scatter的縮寫,整個單詞可能是分布式詞頻率和文檔頻率散發的縮寫。
總結一下,從性能考慮QUERY_AND_FETCH是最快的,DFS_QUERY_THEN_FETCH是最慢的。從搜索的准確度來說,DFS要比非DFS的准確度更高。