日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

ElasticSearch 7.X系列之: 檢索性能優化實戰指南

作者:超超超超子 更新時間: 2022-05-20 編程語言

1、當我們在說 Elasticsearch 檢索性能優化的時候,實際在說什么?!

  • 檢索響應慢!
  • 并發檢索用戶多時,響應時間不達標
  • 卡死了!
  • 怎么還沒有出結果?
  • 怎么這么慢?
  • 為啥競品產品的很快就返回結果了?
  • 宕機了

等等......

這些都與可能檢索有關,確切的說和檢索性能有關。

檢索性能的優化涉及知識點比較零散,我以官方文檔的檢索性能優化部分作為大框架和主線,結合實戰經驗和咨詢經驗用通俗易懂的語言做下解讀。

2、內存要給到位

Elasticsearch 嚴重依賴文件系統緩存來加快搜索速度。通常,你應該確保至少有一半的可用內存進入文件系統緩存,以便 Elasticsearch 可以將索引的熱點區域保留在物理內存中。

線上環境還見過2核4G配置的,基本上跑不了太多數據量。

3、磁盤必要時換 SSD

對寫入速度有超高要求的,SSD就是“祥瑞”。

SSD 成本考慮可能不能一步到位,但至少得是普通機械磁盤。

切記盡量不用:NFS 或 SMB 遠程文件系統。

4、CPU 考慮核數和線程數

在并發寫入或查詢量大之后,就會出現 CPU 打滿的情況。

可以優化的空間就是:基于CPU 核數合理調節線程池和隊列的大小。

5、數據建模要合理

多表關聯非 Elasticsearch 所擅長。換句話說,Elasticsearch 支持多表關聯方式有限。

像 Mysql 中的動不動幾個表的 join 操作,在 Elasticsearch 要考慮必要性和實現復雜度。

Elasticsearch 多表關聯僅限于如下幾種:

  • 父子文檔 join:適用于子文檔頻繁更新場景。
  • nested 嵌套類型:適用于子文檔相對固定、更新頻率低的場景。
  • 大寬表拉伸存儲:本質空間換時間。
  • 業務層面自己結合檢索后的返回結果,自己實現關聯。

且:Nested 可以使查詢慢幾倍,而父子 Join 類型可以使查詢慢數百倍。

大家在建模的時候多考慮,如果不刻意建模全部使用默認字段,看看可能帶來的“災難”性的后果,反過來就能理解建模的重要性。

6、盡可能減少檢索字段數目

query_string 或 multi_match 查詢目標的字段越多,速度就越慢。

提高多個字段搜索速度的常用技術是在索引時將它們的值借助 copy_to 復制到單個字段中,然后在搜索時使用該字段。

copy_to 實現了 1 帶 2 、1 帶 3 甚至 1 帶 N 的效果。

7、合理設置 size 大小

在檢索請求的時候 size 值設置很大,會導致命中數據量大,可能會帶來嚴重的性能問題。

建議:合理設置分頁 size 值。如果著實數據量大考慮:scroll 或者 search_after 實現。

8、多使用寫入前預處理操作

我之前的文章講情感分析區間查詢的時候,其實本質就三個區間:負面、正面、中性。

如果用 range_query 區間檢索勢必會慢。

建模的時候,可以考慮數據寫入的時候,轉成:-1、0、1 的 keyword 類型值。

將 range_query 的范圍檢索變成了基于倒排索引的精準查找 term query,效率自然會提升。

能借助 ingest 預處理完成的,不要放到后面借助 script + update_by_query。

使用過 script + update_by_query的自然知道有多苦。

看到這里有同感的老鐵可以留言說一下感受。

9、能用 keyword 字段類型就不要使用其他

如果一個字段可以設置為:number 數值類型字段也可以設置為 keyword 類型。在建模階段可以參考如下考慮方式實現建模選型。

得看你的應用場景,如果涉及 range query 推薦 number 類型,具體可以:integer、long 或者其他數值類型。

如果僅是精準匹配 term 級別的檢索,那 keyword 就能搞定。

如果還感覺兩種都有可能,建議設置:keyword 和 number 雙類型,借助 fields 實現。

fields 組合類型實現參考如下:

PUT?test_0001
{
??"mappings":?{
????"properties":?{
??????"age":{
????????"type":"integer",
????????"fields":?{
??????????"keyword":{
????????????"type":"keyword"
??????????}
????????}
??????}
????}
??}
}

10、盡量規避使用腳本

如果可能,請避免使用:

  • 基于腳本的排序
  • 基于腳本的聚合
  • 基于script_score 查詢

painless 腳本翻譯為中文是:“無痛”。

但,用過你就知道有多痛。

  • 第一:不是很好用,很多示例,官方文檔也沒有窮盡所有樣例,需要花時間摸索。
  • 第二:性能問題,解決問題一時爽,線上一跑“悔斷腸”。

那,不讓用,線上的確需要咋辦?

盡量前置寫入的時候結合 ingest + script 實現。

如果對寫入指標要求沒有那么高,通過稍微增大寫入的時間間接提高了檢索效率,何樂而不為?

11、日期做舍入處理,能間接利用緩存

GET?index/_search
{
??"query":?{
????"constant_score":?{
??????"filter":?{
????????"range":?{
??????????"my_date":?{
????????????"gte":?"now-1h/m",
????????????"lte":?"now/m"
??????????}
????????}
??????}
????}
??}
}

“/m” 的方式能有效利用時間緩存。

12、有效使用 filter 緩存

在 Elasticsearch 查詢中有效使用 filter 過濾器可以顯著提高搜索性能。

filter 過濾優勢體現在:

  • 緩存。
  • 和query 相比,不需要計算評分,所以更快。

13、對歷史索引數據使用段合并

前提:基于時間切分索引,對于相對冷的數據,訪問密集型沒有那么高的數據,推薦使用段合并。

切記:不要對正在寫入數據的索引進行段合并。

7.X 版本可以借助 ILM 索引生命周期管理實現。

14、啟用 eager global ordinals 提升高基數聚合性能

適用場景:高基數聚合。

高基數聚合場景中的高基數含義:一個字段包含很大比例的唯一值。

global ordinals 的本質是:啟用 eager_global_ordinals 時,會在刷新(refresh)分片時構建全局序號。這將構建全局序號的成本從搜索階段轉移到了數據索引化(寫入)階段。

PUT?my-index-000001
{
??"mappings":?{
????"properties":?{
??????"tags":?{
????????"type":?"keyword",
????????"eager_global_ordinals":?true
??????}
????}
??}
}

15、預熱文件系統緩存

如果重新啟動運行 Elasticsearch 的機器,文件系統緩存將是空的,因此操作系統將索引的熱點區域加載到內存中需要一些時間,以便快速搜索操作。

可以使用 index.store.preload 設置根據文件擴展名明確告訴操作系統哪些文件應該立即加載到內存中。

PUT?/my-index-000001
{
??"settings":?{
????"index.store.preload":?["nvd",?"dvd"]
??}
}

在 lucene 中,

  • nvd 是指:全文檢索文件;
  • dvd 是指:用于聚合排序的列存文件。

16、合理使用 index sort 邊寫入邊排序機制

PUT?my-index-000001
{
??"settings":?{
????"index":?{
??????"sort.field":?"date",?
??????"sort.order":?"desc"??
????}
??},
??"mappings":?{
????"properties":?{
??????"date":?{
????????"type":?"date"
??????}
????}
??}
}

這個配置相信你一看就懂,發生在寫入前,創建索引的時候設定的排序字段。

本質:通過降低寫入速度間接提升檢索速度。

17、通過 perference 優化緩存利用率

perference 用在兩次檢索結果不一致的時候,本質是:主、副本分片數據不一致導致的,有半路由的機制。

合理使用 perference 參數能優化緩存使用率。

18、設置合理的分片數和副本數

主分片的設置需要結合:集群數據節點規模、全部數據量和日增數據量等綜合維度給出值,一般建議:設置為數據節點的1-3倍。

分片不宜過小、過碎。有很多小分片可能會導致大量的網絡調用和線程開銷,這會嚴重影響搜索性能。

副本數不是越多越好?

在許多情況下,擁有更多副本有助于提高搜索性能。但是不代表副本越多越好。

增加副本的前提是考慮:磁盤存儲空間的容量上限和磁盤警戒水位線。本質還是以空間換時間。

一般非高可用場景,基本一個副本足夠。

官方給出了合理副本大小的公式供參考:

如果你的集群有 num_nodes 個節點、num_primaries 主分片,并且你希望最多同時處理 max_failures 個節點故障,那么適合你的副本數為:

?max(max_failures,?ceil(num_nodes?/?num_primaries)?-?1)

19、避免使用 wildcard 檢索

避免使用 wildcard 通配符檢索,尤其是前綴通配符查詢。

我自己早些年線上環境實現曾經大量使用:wildcard,導致客戶現場演示宕機,我自己因此也寫了“檢討書”,血淋淋的教訓再次告訴大家。

幾年后回頭看當時為什么選型 wildcard?復盤原因小結如下:

  • MySql 的使用慣性。

MySql 中 select * from table where title like ‘%長津湖%'。順理成章的認為 Elasticsearch 中的 wildcard 也能實現類型功能。

  • 對 Elasticsearch 不求甚解。

能簡單使用且測試環境小樣沒有問題,直接更新線上環節。客戶現場數據一多,直接崩潰。

  • 為達目的,功能優先,沒有考慮性能。

產品經理要求字段中存在的字符都能檢索出來。

Elasticsearch 本質是倒排索引提高檢索效率,如果分詞詞典不完備,除非 ngram 逐個字符細粒度分詞,否則幾乎做不到的。

wildcard 功能方面必然能滿足,但是性能問題當時沒有做大量測試。

  • 沒有對 Elasticseearch 全局認識

全局看,Elasticsearch 就那么幾種類型,全文檢索類型、精準匹配類型是重頭戲。

當時選型的時候,摸著石頭過河,拿起石頭就用,結果石頭有“刺“,把手給扎了。

更好的方式應該是:全局認識,有幾種類型石頭?哪里有石頭?石頭應用場景是什么?我的業務需要哪種類型的石頭?

后面優化的方案就是:字詞混合索引 + match_phrase 短語匹配實現,一方面保證了匹配的精準性,另一方面保證了召回率。

20、謹慎使用 Regex 正則檢索

正則檢索也會有響應慢及性能問題,要謹慎使用。

21、謹慎使用全量聚合和多重嵌套聚合

聚合的本質是不精準的,原因在于主、副本分片數據的不一致性。

對于實時性業務數據,每分、每秒都有數據寫入的,要考慮數據在變化,聚合結果也會隨之變化。

我在業務開發中使用全量聚合的目的是規避聚合結果的不精準性,但是帶來的則是性能問題。

多重嵌套聚合隨之嵌套層數的增多,復雜度也會激增,檢索響應速度會變慢甚至帶來性能問題。

22、設置合理的 Timeout 時間

超時參數和在參數后終止在執行大量搜索或結果數據龐大時非常有用。

在 python 客戶端或者 java 客戶端連接的時候都建議設置好 Timeout 值。

23、合理設置刪除文檔的方式

當數據量非常大了之后怎么辦?兩種方式做一下對比:

  • 方式一:大索引存儲。

數據量大了之后,刪除部分索引數據,借助:delete_by_uery 實現。

  • 方式二:冷熱集群架構+基于時間切分索引。

必要時候,刪除較早日期的索引,借助:delete 實現。

方式一本質是邏輯刪除,數據看似刪除了,但磁盤空間短期內會暴增。待段合并后,才會物理刪除。

方式二本質是物理刪除,刪除索引會立即釋放磁盤。

所以,當磁盤空間吃緊,尤其到了警戒水位線:85%、90%、95%之后。

方式二刪除:穩、準、狠。而方式一相對“磨磨唧唧、娘娘們們”,非必要不推薦。

參考

https://www.elastic.co/guide/en/elasticsearch/reference/master/tune-for-search-speed.html

https://opster.com/blogs/improve-elasticsearch-search-performance/

https://opster.com/elasticsearch-glossary/elasticsearch-slow-search-query-guide/

https://medium.com/analytics-vidhya/improving-elasticsearch-query-performance-3b59c6b15a97

https://opster.com/elasticsearch-glossary/elasticsearch-increase-search-speed/

原文鏈接:https://blog.csdn.net/g5703129/article/details/124816464

欄目分類
最近更新