Elasticsearch搜索調優權威指南 (2/3)

英文原文:https://qbox.io/blog/elasticsearch-search-tuning-part-2
作者:Adam Vanderbush
譯者:楊振濤

目錄

  1. 預索引數據
  2. 映射
  3. 避免使用腳本
  4. 強制合併只讀索引

Elasticsearch搜索調優權威指南,是QBOX在其博客上發佈的系列文章之一,本文是該系列的第二篇,主要介紹了索引預處理、mapping建立、避免腳本的使用、索引段合併等搜索性能相關的調優方法。

本文是Elasticsearch搜索調優系列文章3篇中的第2篇,第1篇參考這裏(點擊)。本系列教程旨在更進一步討論針對Elasticsearch 5.0及以上版本的搜索調優技術、策略及建議。

1.預索引數據

爲了優化數據的索引方式,應當在查詢中預置一些模式。比如,如果所有文檔都有一個叫 price 的價格字段,並且大部分查詢在一個固定範圍列表上執行 range 聚合,那麼就可以通過預索引範圍到索引中並使用一個 terms 聚合,來加速該聚合。

比如有如下文檔:

curl -XPUT 'ES_HOST:ES_PORT/index/type/1
?pretty' -H 'Content-Type: application/json' -d '{
 "designation": "bowl",
 "price": 13
}'

以及如下搜索請求:

curl -XGET 'ES_HOST:ES_PORT/index/_search
?pretty' -H 'Content-Type: application/json' -d '{
 "aggs": {
   "price_ranges": {
     "range": {
       "field": "price",
       "ranges": [
         { "to": 10 },
         { "from": 10, "to": 100 },
         { "from": 100 }
       ]
     }
   }
 }
}'

然後就可以在索引階段增加一個 price_range 字段,該字段應該映射爲一個關鍵字:

curl -XPUT 'ES_HOST:ES_PORT/index
?pretty' -H 'Content-Type: application/json' -d '{
 "mappings": {
   "type": {
     "properties": {
       "price_range": {
         "type": "keyword"
       }
     }
   }
 }
}'

curl -XPUT 'ES_HOST:ES_PORT/index/type/1
?pretty' -H 'Content-Type: application/json' -d '{
 "designation": "bowl",
 "price": 13,
 "price_range": "10-100"
}'

接下來搜索請求就能聚合這個新的字段,而不是在 price 字段上執行一個範圍聚合。

curl -XGET 'ES_HOST:ES_PORT/index/_search
?pretty' -H 'Content-Type: application/json' -d '{
 "aggs": {
   "price_ranges": {
     "terms": {
       "field": "price_range"
     }
   }
 }
}'

2.映射

事實上,一些數值型的數據,並不意味着總是要被映射爲一個數值型字段。典型的,那些存儲爲諸如 ISBN 之類的標識符,或者任何標識另一個數據庫中記錄的數字的字段,可能映射爲關鍵字比映射爲一個 integer 或 long 類型更好。

關鍵字類型用於索引結構化內容,比如 email 地址、主機名稱、狀態碼、郵政編碼或標籤。

典型地用於過濾(比如查找所有已發佈的博客文章)、排序以及聚合。關鍵字字段只可通過其精確值搜索得到。

如果需要索引全文內容比如 email 內容或產品描述,可能就要使用一個文本字段。

下面是一個關鍵字字段映射的示例:

curl -XPUT 'ES_HOST:ES_PORT/my_index
?pretty' -H 'Content-Type: application/json' -d '{
 "mappings": {
   "my_type": {
     "properties": {
       "tags": {
         "type":  "keyword"
       }
     }
   }
 }
}'

從 2.x 版本導入的索引是不支持關鍵字的;相反,它們會試圖把 keyword 類型降級爲 string 類型。這支持合併新的映射和舊的映射。長期存在的索引,必須在升級到6.x 版本前重建,但是映射降級提供了按自己的計劃實施重建的機會。

3.避免使用腳本

一般來說要儘量避免使用腳本;如果必須要使用,優先選擇 Painless 和表達式引擎。

Painless 是一門簡單安全的腳本語言,專門爲在 Elasticsearch 中使用而設計,是 Elasticsearch 的默認腳本語言,可安全地用於內聯和存儲腳本。關於 Painless 語法和語言特性的更詳細描述,請參考 Painless 語言規範。

請參考 “ Painless Scripting in Elasticsearch ” 更深入地瞭解 Painless 腳本語言指南。

  • Lucene 表達式語言

Lucene 表達式會把一個 javascript 表達式編譯爲字節碼,設計用於高性能自定義評級和排序函數,並支持 inline 和默認的存儲腳本。

  • 性能

表達式相對於自定義 Lucene 代碼而言有着更好的性能表現;其性能相對其他腳本引擎有更低的單文檔成本:表達式更加“領先”。

這就允許非常快的執行,尤其是比自己寫的本地腳本快很多。

  • 語法

表達式支持一個 javascript 語法子集:一個單獨的表達式。參見表達式模塊的文檔,瞭解支持的操作符和函數。

表達式腳本中可訪問的變量有:

  • 文檔字段,比如doc['myfield'].value

  • 字段所支持的變量和方法,比如doc['myfield'].empty

  • 傳遞到腳本里的參數,比如mymodifier

  • 當前文檔得分,_score(僅在 script_score中使用時有效)

表達式腳本可以用於script_score、script_fields、排序腳本以及數值型聚合腳本,只要簡單地設置參數到表達式中即可。

4.強制合併只讀索引

只讀索引在合併爲單一的段後將會非常受益。典型的情況是基於時間的索引:只有當前時間窗的索引會成爲新文檔,同時舊索引成爲只讀。

強制合併 API 支持通過 API 強制合併一個或更多的索引。合併與每個分片中 Lucene索引的段數量有關。強制合併操作支持通過合併來減少段數量。

該調用在合併完成之前將會處於阻塞狀態。如果 http 連接斷掉,請求將在後臺繼續,在前一個強制合併完成之前,所有新請求將會阻塞。

curl _XPOST 'ES_HOST:ES_POST/twitter/_forcemer
ge?pretty'

強制合併 API 接受下列請求參數:

  • max_num_segments - 待合併的段數量。要完全合併索引,可設置爲 1 。默認會簡單檢查一個合併是否需要執行,如果是,就會執行。

  • only_expunge_deletes -合併流程是否僅僅擦除包含刪除的段。在 Lucene 中,一個文檔並不會從一個段直接刪除,只是標記爲刪除。在一個段合併的過程中,一個新的段可能會被創建,這個新的段並不包含那些刪除。這個標記參數支持只合併有刪除的段,且默認爲false。注意,這並不會重寫閾值 index.merge.policy.expunge_deletes_allowed。

  • flush - 強制合併後是否執行 flush,默認爲 true
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章