深入研究Elasticsearch聚合的效能 - Raoul Meyer

banq發表於2019-01-20

Elasticsearch在提高效能方面做了很多工作,我們沒有注意到,我們還能做些什麼來進一步改進它?這是我在研究我們正在使用的一些重型聚合的效能時問自己的問題。在這篇文章中,我給出了Elasticsearch中快取的基本解釋,然後是兩個驗證快取和查詢如何互動的實驗。

Elasticsearch如何快取?
Elasticsearch具有不同級別的快取,所有快取都協同工作以確保它儘可能快地響應。所有快取級別都具有相同的承諾:接近實時響應。這意味著您獲得的響應既快又與資料匹配(或幾乎匹配),因為它當前存在於索引中。

請求快取
Elasticsearch有自己的智慧請求快取。它將根據對底層索引的更新來更新此快取,從而確保快取始終準確。當然有一些問題,例如:

即使在索引設定中啟用了請求快取,也不會快取大小大於0的請求。

請求快取可能不起作用的其他原因是您的響應包含每個請求都更改的值。例如,如果您的響應包含當前日期或某個隨機生成的數字,則會使響應無法快取。

查詢快取
在更深層次上,過濾器型別查詢的結果可以快取到稱為bitset的二進位制表示。就像請求快取一樣,只要索引中的相關內容得到更新,就會自動更新此快取。Elasticsearch僅快取適用於大量文件的查詢:

只有包含超過10,000個文件的段(或總文件的3%,以較大者為準)才會快取該位集。

它這樣做,因為對於較小的段,評估查詢可能更快。有了Elasticsearch已經最佳化了多少沒有快取的效能,透過新增快取可以很容易地減慢速度。您可以在此處找到有關查詢快取的更多資訊。

欄位資料快取​​​​​​​
欄位資料快取與聚合非常相關。正如文件所說:

它將所有欄位值載入到記憶體中,以便提供對這些值的快速文件訪問。

沒有為欄位資料快取保留足夠的記憶體將使您的聚合變慢。您可以監控現場資料快取的使用情況,並根據您的需要進行調整。去這裡更多地瞭解它。

提取常見查詢元素有幫助嗎?
查詢快取似乎對很多真實世界的聚合非常有益。在索引的過濾子集上執行某些聚合是很常見的。在這種情況下,Elasticsearch可以重用過濾嗎?或者我們可以幫助它嗎?

讓我們比較以下查詢的效能。第一個查詢具有為兩個聚合分別指定的相同過濾器:

{
  "size": 0,
  "aggregations": {
    "1": {
      "filter": {
        "match": {
          "search_field": "text"
        }
      },
      "aggregations": {
        "items": {
          "top_hits": {
            "size": 100,
            "_source": {
              "includes": "field1"
            }
          }
        }
      }
    },
    "2": {
      "filter": {
        "match": {
          "search_field": "text"
        }
      },
      "aggregations": {
        "items": {
          "top_hits": {
            "size": 100,
            "_source": {
              "includes": "field2"
            }
          }
        }
      }
    }
  }
}

第二個查詢將此過濾器提取到更高階別,這應該使聚合共享結果。我們需要將過濾器包裝在bool.filter中以確保評分相同:

{
  "query": {
    "bool": {
      "filter": [
        {
          "match": {
            "search_field": "text"
          }
        }
      ]
    }
  },
  "size": 0,
  "aggregations": {
    "1": {
      "top_hits": {
        "size": 100,
        "_source": {
          "includes": "field1"
        }
      }
    },
    "2": {
      "top_hits": {
        "size": 100,
        "_source": {
          "includes": "field2"
        }
      }
    }
  }
}


我們禁用了此測試的請求快取,但查詢快取和欄位資料快取仍可以執行其工作。我們已經確定過濾查詢的段實際上大於10,000個文件。這意味著查詢快取應該為此啟動,並且這兩個查詢之間的查詢時間應該沒有區別。

這兩種解決方案之間沒有效能差異。看起來查詢快取正在很好地完成其工作。請記住查詢快取的要求,您可能仍然更喜歡第二種變體。在這兩種情況下,現場資料快取也同樣有效。

聚合是否並行執行?
在日常工作中,我看到很多情況下我們在一個查詢中放置了大量聚合。這讓我想知道,聚合實際上並行執行嗎?或者我們可以透過例如對每個聚合進行查詢來進行msearch來改善響應時間嗎?
在此測試中,我們執行與以前相同的查詢。我們在一個查詢中使用1,2,5和10個聚合進行測試。我們將它與分割聚合的時間進行比較,因此每個聚合都有自己的查詢。
當我們為每個聚合提供自己的查詢並進行msearch時,我們會看到顯著的效能提升。在10次聚合時,加速比接近2倍。在此測試中,Elasticsearch例項在具有2個可用CPU的docker容器內執行,因此這種加速大約是您期望獲得的最佳速度。
很明顯,聚合不僅僅是預設並行執行。因此,如果您希望縮短響應時間,將聚合拆分為多個查詢可能會有意義。這僅適用於CPU不是瓶頸的情況,因為透過拆分查詢,您將總共使用更多的CPU時間。

結論​​​​​​​
那麼,需要提取常見的查詢元素嗎?一般來說,不需要,因為Elasticsearch可以針對這些情況進行最佳化。如果您的過濾器不適合查詢快取,則在聚合中移動更高階別的常見查詢元素可能仍會稍微提高效能。
聚合是否並行執行?它們不是預設的。只要你還沒有CPU限制,使用msearch拆分它們可能很聰明。在尚未充分利用的群集上,這可以顯著縮短響應時間。​​​​​​​
 

相關文章