檢索錦囊 1:盡可能的使用緩存
對于精準匹配的查詢,不關(guān)注評分結(jié)果,只關(guān)注數(shù)據(jù)是否滿足檢索需求。
可以考慮用 filter “包裹一層”,如處理時間范圍檢索,Elasticsearch 能緩存部分結(jié)果。但,要說明的是更換時間窗口,換不同時間段檢索,原有緩存不起作用。
關(guān)于 filter 的緩存效果,官方文檔如是說:
“Frequently used filters will be cached automatically by Elasticsearch, to speed up performance.”
即:“頻繁的使用過濾器會有自動緩存的“效果”,以提高性能?!?/p>
舉例如下,“/m”的本質(zhì)使檢索不是具體到某秒的精確值,而是擴展到分鐘。
GET?kibana_sample_data_flights/_search
{
??"profile":?true,?
??"query":?{
????"constant_score":?{
??????"filter":?{
????????"range":?{
??????????"timestamp":?{
????????????"gte":?"now-1h/m",
????????????"lte":?"now/m"
??????????}
????????}
??????}
????}
??}
}
加“profile;true”后,看到的檢索結(jié)果如下。

官方文檔解釋的不夠準確,這里結(jié)合 profile:true的結(jié)果,解釋一下。
起始時間:now-1h/m 為當前時間戳減去1分鐘所在分鐘的 00 秒的時刻;
結(jié)束時間:now為當前時間戳所在分鐘的 59秒的時刻。
更為確切的說,時間跨度為 2 分鐘了。

https://www.elastic.co/guide/en/elasticsearch/reference/current/tune-for-search-speed.html#_search_rounded_dates
檢索錦囊 2:文件系統(tǒng)緩存預熱
如果 Elasticsearch 節(jié)點重啟,文件系統(tǒng)緩存通常是空的。
操作系統(tǒng)需要一些時間才能將索引的熱數(shù)據(jù)加載到內(nèi)存中,以便快速檢索。
我們可以通過如下的設(shè)置來告知操作系統(tǒng)哪些文件應(yīng)立即加載到內(nèi)存中。
PUT?/my-index-000001
{
??"settings":?{
????"index.store.preload":?["nvd",?"dvd"]
??}
}
支持的文件擴展名及釋義如下所示。
擴展名 | 英文釋義 | 詳細釋義 |
---|---|---|
.nvd | Norms data | 查詢時使用的各種歸一化因子數(shù)據(jù) |
.dvd | doc values Per-Document Values | 用于聚合、排序的正排索引文件 |
.tim | terms dictionaries | 單詞詞典 |
.doc | Frequencies | 倒排列表,包含:文檔列表及詞頻 |
.dim | points | Point values |
注意:index.store.preload
設(shè)置為“*”通常沒有意義,因為所有文件加載到內(nèi)存中通常沒有用。
而更好的選擇可能是將其設(shè)置為?["nvd", "dvd", "tim", "doc", "dim"],也就是包含 Norms data、docvalues、單詞字典、倒排索引列表等,這些是搜索和聚合中最重要的部分。
https://lucene.apache.org/core/8_0_0/core/org/apache/lucene/codecs/lucene80/package-summary.html
https://www.shenyanchao.cn/blog/2018/12/04/lucene-index-files/
檢索錦囊 3:使用預過濾分片執(zhí)行檢索
大背景是:對于時序數(shù)據(jù),可以使用 ilm 索引生命周期管理,ilm 索引生命周期管理的前置條件是冷熱集群架構(gòu)。也就是:我們有 rollover 滾動索引機制,可以設(shè)置索引在熱節(jié)點、溫節(jié)點、冷節(jié)點的生存時長。
進一步說,索引不是普通的索引,索引有了時間戳的后綴。這樣的好處是:當我們需要檢索數(shù)據(jù)的時候,是可以通過別名等方式物理縮小索引范圍區(qū)間的。
舉個例子:如下圖所示,weibo_2527 實際指的是上面的“20190225,20190226,20190227”三個索引,如果只檢索這三天的數(shù)據(jù),相比于全量數(shù)據(jù),weibo_2527別名意味著極大的降低了檢索數(shù)據(jù)樣本空間。

但,索引層面還足夠大,看上面截圖我們知道,每個索引下面又有 N 多分片。能否繼續(xù)優(yōu)化,下沉到分片層面進行快速鎖定分片執(zhí)行高效檢索呢?
這就用到了 7.4+ 版本才有的新特性:prefilter shard。使用 prefilter shard,Elasticsearch 能夠根據(jù)我們的請求確定需要查詢的分片。
預處理分片的本質(zhì)如張超老師所講:“對于 Date 類型的 Range 查詢,在對分片執(zhí)行搜索之前,先檢查一下分片是否包括被查詢的數(shù)據(jù)范圍,如果查詢的范圍與分片持有的數(shù)據(jù)沒有交集,就跳過該分片?!北举|(zhì)一句話:有助于避免查詢到達不必要的分片。
默認情況下,此預過濾分片階段在以下情況下執(zhí)行:
條件一:該請求針對超過 128 個分片。
條件二:請求針對一個或多個只讀索引。
條件三:基于創(chuàng)建過索引的字段進行排序。
這點,參考張超老師驗證且給出的結(jié)論——“pre-filter 最主要的作用不是降低查詢延遲,而是 pre-filter 階段可以不占用 search theadpool(檢索線程池),相比于不加這個參數(shù),會減少了檢索線程池的占用情況?!?/p>
具體使用方式如下所示。
相當于在原來檢索的基礎(chǔ)上加了:pre_filter_shard_size
參數(shù)。
POST?kibana_sample_data_flights_20220727/_search?pre_filter_shard_size=1000
{
??"query":?{
????"range":?{
??????"timestamp":?{
????????"gte":?"2022-07-01",
????????"lte":"2022-07-31"
??????}
????}
??}
}
https://easyice.cn/archives/350
檢索錦囊 4:合并只讀分片
我們發(fā)現(xiàn),除了借助 rollover (ilm 索引生命周期管理)將冷數(shù)據(jù)索引標記為只讀之外,我們還可以強制合并(force merge)一個或多個索引的分片。與磁盤碎片整理類似,此操作在不涉及緩存時可極大地提高了查詢性能。經(jīng)過只讀分片的合并,最大響應(yīng)時間由 30 秒降到了2 秒。
POST?/.ds-my-data-stream-2099.03.07-000001/_forcemerge?max_num_segments=1&pretty
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-forcemerge.html#forcemerge-api-time-based-index-ex
檢索錦囊 5:新建索引時配置排序方式
在 Elasticsearch 中創(chuàng)建新索引時,可以配置指定每個 Shard 中的 Segments 的排序方式。
默認情況下,Lucene 不應(yīng)用任何排序。index.sort.*
設(shè)置定義了應(yīng)該使用哪些字段來對每個段內(nèi)的文檔進行排序。
舉例:如下索引的定義中(篇幅原因,省略了 Mapping),指定了段內(nèi)基于 timestamp 字段進降序排序。
PUT?kibana_sample_data_flights_20220727
{
??"settings":?{
????"index":?{
??????"sort.field":?"timestamp",
??????"sort.order":?"desc",
??????"number_of_shards":10,
??????"number_of_replicas":0
????}
??},
??"mappings":?{
????"properties":?{
????????....
????????}
??????}
???}
?}
同時,有些業(yè)務(wù)場景,用戶不真正關(guān)心跟蹤命中的總數(shù),并且只希望查詢的Top N 個結(jié)果。這時候可以基于“提前終止查詢”來快速獲取檢索結(jié)果。那么如何做到提前終止查詢呢?
我們都知道:Elasticsearch 默認會在 query 階段查詢每個文檔,基于給定條件排序后,然后在 fetch 階段取滿足排序條件的結(jié)果數(shù)據(jù)并返回給客戶端。
這就意味著分段數(shù)越多,排序自然也會越慢,查詢的時間越久。
提前終止查詢的前置條件是:寫入的時候,已經(jīng)基于字段排序了。假設(shè)我們最終期望返回 Top 10 數(shù)據(jù),每個分段內(nèi)各自取 Top 10 然后再整體排序得到 Top 10,不就可以了嗎?
打個不恰當?shù)念惐?,世界杯需要決出前 10 名,那么:亞洲取前10,歐洲取前10,非洲取前10,美洲取前10,整體排序不就是世界足球 Top10了嗎?

原理明白了,問題就轉(zhuǎn)化為:如何提前終止呢?
實際上并沒有特殊參數(shù)控制,因為我們前置設(shè)置了:"sort.field": "timestamp", Elasticsearch 會根據(jù) size 大小每個分段取 Top 10 數(shù)據(jù)后自動終止。
`"track_total_hits": false`的目的是不顯示文檔總數(shù),這也能降低檢索時間,提高檢索效率。
執(zhí)行操作如下所示。
POST?_reindex
{
??"source":?{
????"index":?"kibana_sample_data_flights"
??},
??"dest":?{
????"index":?"kibana_sample_data_flights_20220727"
??}
}
POST?kibana_sample_data_flights_20220727/_search
{
??"size":?10,
??"sort":?[
????{
??????"timestamp":?"desc"
????}
??],
??"track_total_hits":?false
}
https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-index-sorting.html#early-terminate
6、小結(jié)
在查詢中使用近似日期(now/m)而非精準日期格式,以利用節(jié)點查詢緩存。
時序數(shù)據(jù)場景,可以將冷數(shù)據(jù)顯示設(shè)置為只讀來強制執(zhí)行預過濾分片機制。
必要時對索引執(zhí)行強制合并(force merge),確?!傲闼椤钡姆制喜橐粋€大分段,以提高檢索效率。
關(guān)閉超過一年+的索引(具體結(jié)合業(yè)務(wù)需求,如果還在用就不能關(guān)),以減少打開的分片數(shù)量,避免將資源浪費到無用的數(shù)據(jù)上。
借助索引生命周期管理 ILM 管理時序數(shù)據(jù),實現(xiàn)索引數(shù)據(jù)的 rollover(滾動),設(shè)置只讀、強制合并及索引關(guān)閉任務(wù),而不是手動執(zhí)行這種操作。
在“每月存儲大約 新增 500 萬+數(shù)據(jù),每天后端接收 2萬次查詢請求”的實戰(zhàn)業(yè)務(wù)場景下,如上的優(yōu)化效果卓著??磳Ρ刃Ч麍D:
檢索對比 | 平均響應(yīng)時間(秒) | 最長響應(yīng)時間(秒) | 最短響應(yīng)時間(秒) |
---|---|---|---|
優(yōu)化前 | 4.619 | 29.863 | 0.365 |
優(yōu)化后 | 0.059 | 1.806 | 0.010 |
如上文章翻譯自:https://medium.com/teads-engineering/practical-elasticsearch-performance-tuning-on-aws-8c08066e598c
我做了細節(jié)展開解讀。
你的業(yè)務(wù)開發(fā)或運維中如何做的檢索優(yōu)化呢?歡迎留言討論交流。
推薦閱讀
如何從0到1打磨一門 Elasticsearch 線上直播課?
重磅 | 死磕 Elasticsearch 方法論認知清單(2021年國慶更新版)
如何系統(tǒng)的學習 Elasticsearch ?
Elasticsearch 檢索性能優(yōu)化實戰(zhàn)指南
Elasticsearch大文件檢索性能提升20倍實踐(干貨)
讓Elasticsearch飛起來!——性能優(yōu)化實踐干貨
文章來源:http://www.zghlxwxcb.cn/news/detail-428472.html
比同事?lián)屜纫徊綄W習進階干貨!文章來源地址http://www.zghlxwxcb.cn/news/detail-428472.html
到了這里,關(guān)于Elasticsearch 8.X 檢索實戰(zhàn)調(diào)優(yōu)錦囊 001的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!