天天看點

es 多條件查詢_ES優化最佳實踐

原文連結

https://www.jianshu.com/p/883325b7bbda

1、bool 查詢的 filter 篩選

衆所周知,ES中filter是不參與相關性評分的,是以查詢子句可以被系統進行緩存,性能要高于普通的query查詢。

bool查詢中支援4種子句,分别是filter、must、must_not、should,其中filter和must_not屬于過濾器,過濾器查詢先于其它查詢執行。

另外在function_score、constant_score中也可以使用filter子句進行查詢緩存。

2、設定indices.memory.index_buffer_size

indices.memory.index_buffer_size預設是jvm大小的10% ,将該值調大到20%,經常查詢的索引分片資料會被緩存,當該值足夠大時緩存的資料就會更多,查詢就會更快。

3、segment merge

  • 增加 Index Refresh 間隔,目的是減少 Segment Merge 的次數,建議設定為30s-90s
  • 定期将隻讀或寫少的索引進行segment合并,降低segment數量對搜尋性能提升幫助很大,合并過程中将only_expunge_deletes設定為true意思是将标記為删除的資料清除掉。
curl -XPOST "http://host/visitor/_forcemerge?only_expunge_deletes=true&max_num_segments=1&flush=true"
           

4、SearchType

SearchType預設是QUERY_THEN_FETCH,可在查詢時指定為dfs_query_then_fetch,這樣協調節點隻需要請求一次資料節點就可以完成請求處理了。

QUERY_THEN_FETCH:ES 預設的搜尋方式。第一步,先向所有的分片發請求,各分片隻傳回文檔的相似度得分和文檔的 ID,然後協調節點按照各分片傳回的分數進行重新排序和排名,再取出需要傳回給用戶端的 Size 個文檔 ID。
第 2 步,在相關的分片中取出文檔的詳細資訊并傳回給使用者。

QUERY_AND_FETCH:協調節點向所有分片發送查詢請求,各分片将文檔的相似度得分和文檔的詳細資訊一起傳回。
然後,協調節點進行重新排序,再取出需要傳回給用戶端的資料,将其傳回給用戶端。由于隻需要在分片中查詢一次,是以性能是最好的。

DFS_QUERY_THEN_FETCH:與 QUERY_THEN_FETCH 類似,但它包含一個額外的階段:在初始查詢中執行全局的詞頻計算,以使得更精确地打分,進而讓查詢結果更相關。
QUERY_THEN_FETCH 使用的是分片内部的詞頻資訊,而 DFS_QUERY_THEN_FETCH 使用通路公共的詞頻資訊,是以相比 QUERY_THEN_FETCH 性能更低。

DFS_QUERY_AND_FETCH:與 QUERY_AND_FETCH 類似,不過使用的是全局的詞頻。

           
/_search?preference=abcd&search_type=dfs_query_then_fetch
#preference 可以確定字元串辨別相同時,每次請求會發送到相同的分片執行
           

5、預排序 IndexSorting

ES 6.x之後新增預排序功能,即索引在建立之前可以指定資料寫入後的排序方式,當query時指定的排序方式和預排序邏輯一緻時将能夠很快獲得排序結果,需要注意的是 查詢時不能開啟total值

{
"settings": {
"index": {
"sort.field": [ "username", "date" ], 
"sort.order": [ "asc", "desc" ]       
}
},
"mappings": {
"properties": {
"username": {
"type": "keyword",
"doc_values": true
},
"date": {
"type": "date"
}
}
}
}
           
{
"size": 10,
"sort": [ 
{ "username": "asc" },
{ "date": "desc" }
],
"track_total_hits": false
}

           

6、磁盤

有條件的盡量使用SSD盤,或者挂載多塊盤提升io性能,以下是不同磁盤在并發場景下的性能表現:

es 多條件查詢_ES優化最佳實踐

image.png

7、設定獨立的聚合節點

在有聚合分析場景的業務需要單獨指定高配伺服器用于聚合查詢,與現有點查服務進行隔離;一般要求CPU在16核以上

# 查詢聚合節點配置(conf/elasticsearch.yml):
node.master:false
node.data:false
node.ingest:false
           

8、查詢中斷

如果不需要精确統計查詢命中記錄條數,可以配 teminate_after 指定每個 shard 最多比對 N 條記錄後傳回,以及設定查詢逾時時間 timeout 使得請求提前結束

{ 
"timeout": "10s",
"terminate_after": 1000,
"query": {

}
}

           

9、調整聚合方式

預設深度優先聚合改為廣度優先聚合。

"collect_mode" : "breadth_first"

  • depth_first 直接進行子聚合的計算
  • breadth_first 先計算出目前聚合的結果,針對這個結果在對子聚合進行計算。

10、索引冷熱分離

一般應用在操作時序日志的場景, 通過定義模闆動态生成索引,如将超出3個月的索引通過定時任務歸檔到cold組 ,具體操作如下:

1、将data node劃分為冷熱資料節點

# cat elasticsearch.yml    // 配置檔案設定tag區分
node.attr.tag: cold/hot

# bin/elasticsearch -d -Enode.attr.box_type=hot  //啟動設定

           

2、根據模闆按月生成索引,格式如 visitor_2019-01

#建構索引模闆,滾動新增的索引将按照模闆進行建立
curl -X PUT "localhost:9200/_template/visitor" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["visitor_*"], 
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1,
"index.routing.allocation.include.tag" : "hot"
},
"mappings": {}
}
'
           

3、歸檔曆史資料到cold節點

curl -X PUT "${es}/${i}/_settings" -H 'Content-Type: application/json' -d'{
        "number_of_replicas": 0,
        "index.routing.allocation.include.tag": "cold"
     }'

           

其它配置說明

cluster.name:elasticsearch:配置 ES 的叢集名稱,預設值是 ES,建議改成與所存資料相關的名稱,ES 會自動發現在同一網段下的叢集名稱相同的節點。

node.nam:"node1":叢集中的節點名,在同一個叢集中不能重複。節點的名稱一旦設定,就不能再改變了。當然,也可以設定成伺服器的主機名稱,例如 node.name:${HOSTNAME}。

noed.master:true:指定該節點是否有資格被選舉成為 Master 節點,預設是 True,如果被設定為 True,則隻是有資格成為 Master 節點,具體能否成為 Master 節點,需要通過選舉産生。

node.data:true:指定該節點是否存儲索引資料,預設為 True。資料的增、删、改、查都是在 Data 節點完成的。

index.number_of_shards:5:設定都索引分片個數,預設是 5 片。也可以在建立索引時設定該值,具體設定為多大都值要根據資料量的大小來定。如果資料量不大,則設定成 1 時效率最高。

index.number_of_replicas:1:設定預設的索引副本個數,預設為 1 個。副本數越多,叢集的可用性越好,但是寫索引時需要同步的資料越多。

path.conf:/path/to/conf:設定配置檔案的存儲路徑,預設是 ES 目錄下的 Conf 檔案夾。建議使用預設值。

path.data:/path/to/data1,/path/to/data2:設定索引資料多存儲路徑,預設是 ES 根目錄下的 Data 檔案夾。切記不要使用預設值,因為若 ES 進行了更新,則有可能資料全部丢失。

可以用半形逗號隔開設定的多個存儲路徑,在多硬碟的伺服器上設定多個存儲路徑是很有必要的。

path.logs:/path/to/logs:設定日志檔案的存儲路徑,預設是 ES 根目錄下的 Logs,建議修改到其他地方。

path.plugins:/path/to/plugins:設定第三方插件的存放路徑,預設是 ES 根目錄下的 Plugins 檔案夾。

bootstrap.mlockall:true:設定為 True 時可鎖住記憶體。因為當 JVM 開始 Swap 時,ES 的效率會降低,是以要保證它不 Swap。

network.bind_host:192.168.0.1:設定本節點綁定的 IP 位址,IP 位址類型是 IPv4 或 IPv6,預設為 0.0.0.0。

network.publish_host:192.168.0.1:設定其他節點和該節點互動的 IP 位址,如果不設定,則會進行自我判斷。

network.host:192.168.0.1:用于同時設定 bind_host 和 publish_host 這兩個參數。

http.port:9200:設定對外服務的 HTTP 端口,預設為 9200。ES 的節點需要配置兩個端口号,一個對外提供服務的端口号,一個是叢集内部使用的端口号。

http.port 設定的是對外提供服務的端口号。注意,如果在一個伺服器上配置多個節點,則切記對端口号進行區分。

transport.tcp.port:9300:設定叢集内部的節點間互動的 TCP 端口,預設是 9300。注意,如果在一個伺服器配置多個節點,則切記對端口号進行區分。

transport.tcp.compress:true:設定在節點間傳輸資料時是否壓縮,預設為 False,不壓縮。

index.merge.scheduler.max_thread_count:1    #索引merge最大線程數

index.translog.durability:async             #這個可以異步寫硬碟,增大寫的速度

index.translog.sync_interval:120s           #translog間隔時間

thread_pool.bulk.size:20                    #寫入線程個數 由于我們查詢線程都是在代碼裡設定好的,我這裡隻調節了寫入的線程數

thread_pool.bulk.queue_size:1000            #寫入線程隊列大小

index.refresh_interval:300s                 #index重新整理間隔

discovery.zen.minimum_master_nodes:1:設定在選舉 Master 節點時需要參與的最少的候選主節點數,預設為 1。如果使用預設值,則當網絡不穩定時有可能會出現腦裂。

合理的數值為(master_eligible_nodes/2)+1,其中 master_eligible_nodes 表示叢集中的候選主節點數。

discovery.zen.ping.timeout:3s:設定在叢集中自動發現其他節點時 Ping 連接配接的逾時時間,預設為 3 秒。

在較差的網絡環境下需要設定得大一點,防止因誤判該節點的存活狀态而導緻分片的轉移。
           
es 多條件查詢_ES優化最佳實踐