Elasticsearch核心技術(五):搜索API和搜索運行機制

本文將從數據存儲和搜索的角度簡單分析Elasticsearch的搜索運行機制,主要涉及搜索API、搜索機制、存在問題和解決方案。

4.1 Search API

Search API允許用戶執行一個搜索查詢並返回匹配查詢的搜索命中結果。

Elasticsearch查詢主要有兩種方式:URI SearchRequest Body Search

  • URI Search:通過URI參數實現搜索,特點是操作簡便,僅包含部分查詢語法,常用參數如下:
    q:指定查詢語句,使用Query String Syntax
    df:默認欄位,不指定時,會對所有欄位進行查詢
    sort:排序
    profile:用於查看查詢是如何被執行的

  • Request Body Search:完備的查詢語法Query DSL,所以還是建議使用Request Body Search。

4.2 深入了解Search運行機制

建議先參考上篇Elasticsearch核心技術(四):索引原理分析,其中主要介紹了ES的分散式存儲架構和原理。

4.2.1 Query-then-Fetch運行機制

Elasticsearch的分散式搜索的運行機制稱為Query-then-Fetch。具體分為Query和Fetch兩個階段:

Query階段

用戶發出搜索請求到達ES節點。節點收到請求後,會以協調節點(Coordinating Node)的身份,在6個主副分片中隨機選擇3個分片,發送查詢請求。

被選中的節點,進行排序(根據score值進行排序)。然後每個分片都返回 From+size 個排序後的文檔id和排序值給協調節點。 注意這裡返回的是文檔id。

Fetch階段

Coordinating節點將Query階段從每個分片獲取的排序的文檔id列表重新進行排序,選取 From 到 From+size 個文檔的id。

multi get請求的方式,到相應的分片獲取詳細的文檔數據。

4.2.2 為什麼需要兩階段才能完成搜索

因為Elasticsearch在查詢的時候不知道文檔位於哪個分片,因此索引的所有分片都要參與搜索,然後協調節點將結果合併,在根據文檔ID獲取文檔內容。例如現在有5個分片,需要查詢匹配度Top10的數據,那麼每個分片都要查詢出當前分片的Top10的數據,協調節點將5×10個結果再次進行排序,返回Top10的結果給客戶端。

4.2.3 Query-then-Fetch存在問題和解決方案

Query-then-Fetch存在問題分為兩方面,一個是性能問題,一個是相關性算分問題。

  • 性能問題

性能問題主要表現為深度分頁的問題。Elasticsearch數據是分片存儲的,數據分布在多台機器上。有這樣一個場景,如何獲取前1000個文檔?當獲取從990-1000的文檔時候,會在每個分片上面都先獲取1000個文檔,然後再由協調節點聚合所有分片的結果在排序選取前1000個文檔。

這個過程有什麼問題嗎?當然是有的,頁數越深,處理文檔越多,佔用記憶體越多,耗時越長。所以要盡量避免深度分頁。當然,ES官方也注意了這個問題,所以通過index.max_result_window限定最多到10000條數據。當然我們也可以根據業務需要修改這個參數,這也解釋了:為什麼Google搜索結果只有相關度最高的17頁結果,百度只有76頁的結果,原因之一是受限於Elasticsearch深度分頁的性能問題。

  • 相關性算分問題
    另外一個問題是相關性算分不準確問題。每個分片都基於自己分片上面的數據進行相關度計算。這會導致打分偏離的情況,特別是數據量很少的時候。相關性算分在分片之間是相互獨立。當文檔總數很少的情況下,如果主分片大於1,如果主分片數越多,相關性算分會越不準。

  • 如何解決算分不準的問題?

  1. 當數據量不大的時候,將主分片數設置為1;當數據量足夠大的時候,只要保證文檔均勻分布在各個分片上面,結果一般不會出現偏差
  2. 使用DFS Query Then Fetch
    在搜索的URL中指定參數 _search?search_type=dfs_query_then_fetch ;這樣就可以保證每個分片把各個分片的詞頻和文檔頻率進行搜集,然後進行一次相關性算分。但是這樣會耗費更多的CPU和記憶體資源,執行性能較低。
  • 如何避免深度分頁的問題?

使用Search_After
ES提供實時的下一頁文檔獲取功能,這個功能只能下一頁,不能上一頁;
不能指定頁數,不能使用from參數;

  • 三種分頁方式對比:
類型 場景
From/Size 需要實時獲取頂部的部分文檔,且需要自由翻頁
Scroll 需要全部文檔,如導出所有數據的功能
Search_After 需要全部文檔,不需要自由翻頁

4.3 總結

經濟基礎決定上層建築,ES的分片存儲決定了搜索機制。其實存儲和搜索不能分割開來看,只存儲不可搜索,這個存儲是沒有意義的;只搜索沒有存儲(數據源)是空中樓閣。