1、背景
在生產(chǎn)使用中,Elasticsearch 除了精確匹配的要求,也會(huì)有模糊查詢的場(chǎng)景。
2、解決方案探討
面對(duì)這種問(wèn)題 ,傳統(tǒng)的解決方案有兩種:
2.1 方案一:ngram 分詞器
使用 ngram 分詞器對(duì)存入的數(shù)據(jù)進(jìn)行精細(xì)化的拆分,利用細(xì)顆粒度的 token 進(jìn)行快速的召回。
這是一個(gè)利用空間換時(shí)間的方案,細(xì)化查詢所需的詞根內(nèi)容,利用精確匹配結(jié)果大范圍的命中來(lái)達(dá)到模糊效果。
PUT?test-005
{
??"settings":?{
????"index.max_ngram_diff":?10,
????"analysis":?{
??????"analyzer":?{
????????"my_analyzer":?{
??????????"tokenizer":?"my_tokenizer"
????????}
??????},
??????"tokenizer":?{
????????"my_tokenizer":?{
??????????"type":?"ngram",
??????????"min_gram":?3,
??????????"max_gram":?10,
??????????"token_chars":?[
????????????"letter",
????????????"digit"
??????????]
????????}
??????}
????}
??},
??"mappings":?{
????"properties":?{
??????"title":?{
????????"type":?"text",
????????"analyzer":?"my_analyzer",
????????"fields":?{
??????????"keyword":?{
????????????"type":?"keyword"
??????????}
????????}
??????}
????}
??}
}
?
POST?test-005/_bulk
{"index":{"_id":1}}
{"title":"英文官網(wǎng)承認(rèn)劉強(qiáng)東一度被捕的原因是涉嫌性侵"}
{"index":{"_id":2}}
{"title":"別提了朋友哥哥劉強(qiáng)東窗事發(fā)了"}
{"index":{"_id":3}}
{"title":"劉強(qiáng)東施效顰,沒(méi)想到竟然收獲了流量"}
{"index":{"_id":4}}
{"title":"劉強(qiáng)東是誰(shuí)?我不認(rèn)識(shí)"}
?
POST?test-005/_search
{
??"query":?{
????"match_phrase":?{
??????"title":?"劉強(qiáng)東"
????}
??}
}
優(yōu)點(diǎn):召回快,性能消耗?。?/p>
缺點(diǎn):有不小的空間消耗,顆粒度越細(xì),消耗越大。同時(shí),有一定的學(xué)習(xí)成本,需要對(duì)分詞器有成熟的了解,不適合新手。
這里有個(gè)明顯的使用案例,如下圖所示,使用 ngram 的 test2 索引比原來(lái)使用 keyword 的索引空間大小大了接近10倍。
2.2 方案二:wildcard 查詢
使用 wildcard 查詢,這是一項(xiàng)支持通配符的模糊檢索功能,有點(diǎn)類似 SQL 中的 like 匹配。
為了實(shí)現(xiàn)通配符和正則表達(dá)式的查詢,Ealsticsearch 依賴的 Lucene4.0 會(huì)將輸入的字符串模式構(gòu)建成一個(gè)DFA (Deterministic Finite Automaton),而帶有通配符的pattern構(gòu)造出來(lái)的DFA可能會(huì)很復(fù)雜,開(kāi)銷很大。
具體分析:
https://elasticsearch.cn/article/171?
https://elasticsearch.cn/article/186
優(yōu)點(diǎn):使用簡(jiǎn)單,也不需要額外的存儲(chǔ)資源。
缺點(diǎn):性能消耗巨大,濫用則可能會(huì)造成線上事故。
面對(duì)兩個(gè)各有所長(zhǎng),甚至有點(diǎn)“臥龍鳳雛”的方案,ES 在 7.9 版本推出了 wildcard 字段類型來(lái)解決模糊匹配的場(chǎng)景需求。
3、wildcard 類型使用詳解
Elasticsearch 的 wildcard 字段類型最早在 7.9 版本中引入。這個(gè)版本加入了對(duì) wildcard 類型的支持,旨在改善模糊匹配的查詢效率和性能,特別是在處理大量文本數(shù)據(jù)時(shí)。這一新特性主要針對(duì)了之前版本中 wildcard 查詢的性能問(wèn)題,提供了更高效的方式來(lái)處理通配符和正則表達(dá)式的搜索需求。
https://www.elastic.co/guide/en/elasticsearch/reference/7.9/release-highlights.html
我們先來(lái)看下 wildcard 類型怎么使用:
先定義一個(gè) wildcard 類型的字段
PUT?my-index-000001
{
??"mappings":?{
????"properties":?{
??????"my_wildcard":?{
????????"type":?"wildcard"
??????}
????}
??}
}
為其寫(xiě)入一個(gè)文檔
PUT?my-index-000001/_doc/1
{
??"my_wildcard"?:?"This?string?can?be?quite?lengthy"
}
然后使用 wildcard 查詢?nèi)缦滤荆?/p>
GET?my-index-000001/_search
{
??"query":?{
????"wildcard":?{
??????"my_wildcard":?"*quite*lengthy"
????}
??}
}
結(jié)果為
{
??"took"?:?6,
??"timed_out"?:?false,
??"_shards"?:?{
????"total"?:?1,
????"successful"?:?1,
????"skipped"?:?0,
????"failed"?:?0
??},
??"hits"?:?{
????"total"?:?{
??????"value"?:?1,
??????"relation"?:?"eq"
????},
????"max_score"?:?3.8610575,
????"hits"?:?[
??????{
????????"_index"?:?"my-index-000001",
????????"_type"?:?"_doc",
????????"_id"?:?"1",
????????"_score"?:?3.8610575,
????????"_source"?:?{
??????????"my_wildcard"?:?"This?string?can?be?quite?lengthy"
????????}
??????}
????]
??}
}
有時(shí)候我們需要忽略大小寫(xiě),可以在 wildcard 查詢使用 case_insensitive 參數(shù)。
GET?my-index-000001/_search
{
??"query":?{
????"wildcard":?{
??????"my_wildcard":?{
????????"value":?"*Quite*lengthy",
????????"case_insensitive":?true
??????}
????}
??}
}
4、wildcard 原理
關(guān)于 wildcard 字段的實(shí)現(xiàn),官方在推出該字段的時(shí)候發(fā)布了相關(guān)的說(shuō)明:
新的 wildcard 字段使用以下兩種數(shù)據(jù)結(jié)構(gòu)以這種方式自動(dòng)加速通配符和正則表達(dá)式搜索:
字符串中所有3個(gè)字符序列的 ?n-gram 索引。
完整原始文檔值的 “二進(jìn)制 doc value”?存儲(chǔ)。第一點(diǎn),底層還是 ngram 的分詞去實(shí)現(xiàn)模糊查詢的場(chǎng)景,但是這里的 ngram 顆粒度是 3,從功能上滿足了模糊查詢的需求和保證了 wildcard 查詢的高性能。
第二點(diǎn),使用了 ES 中常見(jiàn)的正排+列存數(shù)據(jù)存儲(chǔ)格式 doc value,在這里一個(gè)主要的效果就是在自動(dòng)查詢驗(yàn)證由 n-gram 語(yǔ)法匹配產(chǎn)生匹配候選的同時(shí)利用了doc value格式相對(duì)較高的壓縮比。
5、測(cè)試
現(xiàn)在來(lái)看下 wildcard 實(shí)際的表現(xiàn)。
5.1 空間大小
如下圖所示,可以看到使用 wildcard 字段的索引與原索引相差不大。
5.2 查詢效率
查詢dsl | keyword類型 | wildcard類型 |
---|---|---|
wildcard:”紅豆” | 715ms | 71ms |
wildcard:”006-612014” | 633ms | 22ms |
wildcard:”55” | 584ms | 188ms |
wildcard:”11” | 1359ms | 357ms |
注:這里省卻了索引詳細(xì)信息,只需知道是同一個(gè)索引的比對(duì)測(cè)試。
綜上所述,在模糊搜索字段區(qū)分度很低的情況下 如:模糊查詢單個(gè)數(shù)字,此時(shí)優(yōu)化效率rt大概是之前的1/3左右,區(qū)分度高的場(chǎng)景rt大概是之前的1/15左右,有明顯效果。
6、小結(jié)
1.可以說(shuō) wildcard 字段類型滿足了模糊查詢的主要需求,同時(shí)也提供了相對(duì)較高的查詢性能;
2.wildcard 針對(duì)于 ngram 分詞器有著不小的空間優(yōu)勢(shì)。
3.wildcard 雖然有著不小的優(yōu)勢(shì),但是查詢效率與數(shù)據(jù)的區(qū)分度有著很強(qiáng)的關(guān)聯(lián),在一些區(qū)分度較低的場(chǎng)景下效率與性能消耗依舊很嚴(yán)重。
4.相比 ES 在精確查詢場(chǎng)景優(yōu)秀的性能表現(xiàn)(即 term keyword 的高效,平穩(wěn)在毫秒級(jí)的返回),wildcard 字段在模糊查詢場(chǎng)景下的使用還是需要研發(fā)人員根據(jù)實(shí)際場(chǎng)景測(cè)試選擇。
7、作者介紹
金多安,Elastic 認(rèn)證專家,Elastic資深運(yùn)維工程師,死磕Elasticsearch知識(shí)星球嘉賓,星球Top活躍技術(shù)專家,搜索客社區(qū)日?qǐng)?bào)責(zé)任編輯
銘毅天下審稿并做了部分微調(diào)。
推薦閱讀
全網(wǎng)首發(fā)!從 0 到 1 Elasticsearch 8.X 通關(guān)視頻
重磅 | 死磕 Elasticsearch 8.X 方法論認(rèn)知清單
如何系統(tǒng)的學(xué)習(xí) Elasticsearch ?
2023,做點(diǎn)事
更短時(shí)間更快習(xí)得更多干貨!
和全球?近2000+?Elastic 愛(ài)好者一起精進(jìn)!
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-757601.html
比同事?lián)屜纫徊綄W(xué)習(xí)進(jìn)階干貨!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-757601.html
到了這里,關(guān)于Elasticsearch 查詢革新:探索 Wildcard 類型的高效模糊匹配策略的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!