一文詳解為什么用ElasticSearch以及和傳統(tǒng)數(shù)據(jù)庫MySQL有什么區(qū)別
Elasticsearch 深度解析:從原理到實踐
一、為什么選擇 Elasticsearch?
數(shù)據(jù)模型
Elasticsearch 是基于文檔的搜索引擎,它使用 JSON 文檔來存儲數(shù)據(jù)。在 Elasticsearch 中,相關(guān)的數(shù)據(jù)通常存儲在同一個文檔中,而不是分散在多個表中。
MySQL 是一個關(guān)系型數(shù)據(jù)庫管理系統(tǒng),它使用表、行和列的結(jié)構(gòu)來組織數(shù)據(jù)。數(shù)據(jù)通過外鍵關(guān)系分散在多個表中。
查詢語言
Elasticsearch 使用 Query DSL(Domain Specific Language),這是一種非常靈活的查詢語言,基于 JSON,支持全文搜索、復(fù)合查詢、過濾以及聚合等。
MySQL 使用 SQL(Structured Query Language),這是一種強類型和非常成熟的語言,專門用于查詢和管理關(guān)系數(shù)據(jù)庫。
全文搜索
Elasticsearch 的核心功能是全文搜索。它對數(shù)據(jù)進(jìn)行索引時會自動建立全文搜索索引,使其在搜索大量文本數(shù)據(jù)時表現(xiàn)優(yōu)異。
MySQL 雖然也提供了基本的全文搜索功能,但其主要設(shè)計目標(biāo)是處理結(jié)構(gòu)化數(shù)據(jù)的存儲和查詢,對全文搜索的支持不如 Elasticsearch 那樣強大。
事務(wù)支持
Elasticsearch 不支持傳統(tǒng)的 ACID(原子性、一致性、隔離性、持久性)事務(wù)。雖然它確保了單個文檔操作的原子性,但不適用于跨多個文檔的復(fù)雜事務(wù)。雖然 Elasticsearch 不支持傳統(tǒng)的事務(wù),但是他是可以確保單個文檔的更改(如創(chuàng)建、更新、刪除)是原子性的。這意味著任何文檔級的操作都完整地成功或完整地失敗,但不保證跨多個文檔或操作的一致性。
MySQL 支持 ACID 事務(wù),這使得它非常適合需要嚴(yán)格數(shù)據(jù)一致性的應(yīng)用,如金融服務(wù)和其他商業(yè)數(shù)據(jù)處理。
支持樂觀鎖:
Elasticsearch 支持通過使用文檔版本控制來實現(xiàn)樂觀鎖。
6.7之前。在 ES 中,每個文檔存儲時都有一個 _version 字段,這個版本號在每次文檔更新時自動增加。當(dāng)我們執(zhí)行更新、刪除或者使用腳本處理文檔時,可以指定這個版本號來確保正在操作的文檔是預(yù)期中的版本。如果操作中的版本號與存儲在索引中的文檔版本號不一致,說明文檔已被其他操作更改,當(dāng)前操作將會失敗。(CAS)
為什么_version在后續(xù)版本被拋棄
_version 機制是基于單一遞增整數(shù),它主要適用于簡單的沖突檢測,但在復(fù)雜的分布式系統(tǒng)中,僅依靠版本號可能無法準(zhǔn)確地反映數(shù)據(jù)的歷史和復(fù)制狀態(tài)。尤其是在發(fā)生網(wǎng)絡(luò)分區(qū)或節(jié)點故障時,僅憑 _version 可能導(dǎo)致數(shù)據(jù)丟失或過時的數(shù)據(jù)被錯誤地寫入。
主要還是在高并發(fā)和高可用的環(huán)境下,單一的-version不足以處理因節(jié)點故障或網(wǎng)絡(luò)問題導(dǎo)致的多個副本之間的數(shù)據(jù)不一致問題。
然而if_seq_no 和 if_primary_term這兩個參數(shù)可以更準(zhǔn)確地確定操作是否應(yīng)當(dāng)被執(zhí)行,可以跟蹤每個文檔變更的序列號和主分片的期限。這種機制幫助確保即使在集群狀態(tài)發(fā)生變化(如分片重新分配到新的節(jié)點)的情況下,也不會應(yīng)用基于過時副本的更新。它有效地防止了腦裂問題。
6.7之后,使用 _version 關(guān)鍵字進(jìn)行樂觀鎖已經(jīng)被廢棄了,替代方法是使用
if_seq_no (是一個遞增的序列號,表示文檔的每次修改)和
if_primary_term(表示主分片的當(dāng)前任期,每當(dāng)主分片發(fā)生變化時,這個值會增加。)
來指定版本。
1. 核心優(yōu)勢()
維度 | Elasticsearch | MySQL |
---|---|---|
數(shù)據(jù)模型 | 文檔型(JSON),動態(tài)映射 | 關(guān)系型(嚴(yán)格Schema) |
搜索能力 | 全文檢索、模糊匹配、語義分析 | 僅支持精確查詢和簡單LIKE |
擴展性 | 分布式架構(gòu),自動分片/副本 | 分庫分表復(fù)雜 |
吞吐量 | 單集群支持每秒10萬+查詢 | 高并發(fā)寫入更優(yōu) |
一致性 | 最終一致性(近實時) | 強一致性(ACID) |
Elasticsearch是一個開源的分布式搜索和分析引擎,主要適用于以下場景:
1:搜索引擎:用于快速檢索文檔、商品、新聞等。
2:日志分析:通過分析日志數(shù)據(jù),幫助企業(yè)了解其業(yè)務(wù)的性能情況。
3:數(shù)據(jù)分析:幫助數(shù)據(jù)科學(xué)家和數(shù)據(jù)分析師進(jìn)行數(shù)據(jù)分析,以獲取有價值的信息。
4:商業(yè)智能:幫助企業(yè)制定數(shù)據(jù)驅(qū)動的決策,以實現(xiàn)商業(yè)上的成功。
5:實時監(jiān)控:幫助企業(yè)實時監(jiān)測系統(tǒng)性能、監(jiān)控數(shù)據(jù)變化,以保證系統(tǒng)正常運行。
6:安全性:幫助企業(yè)保證數(shù)據(jù)的安全性,保證數(shù)據(jù)不被非法竊取。
7:應(yīng)用程序開發(fā):幫助開發(fā)人員開發(fā)基于搜索的應(yīng)用程序,以增加用戶體驗。
Elasticsearch具有以下幾個優(yōu)勢:
1:高性能:Elasticsearch具有高性能的搜索和分析能力,其中涵蓋了多種查詢語言和數(shù)據(jù)結(jié)構(gòu)。
2:可擴展性:Elasticsearch是分布式的,可以通過增加節(jié)點數(shù)量擴展搜索和分析能力。
3:靈活性:Elasticsearch支持多種數(shù)據(jù)類型,支持多種語言,支持動態(tài)映射,允許快速地調(diào)整模型以適應(yīng)不同的需求。
4:實時分析:Elasticsearch支持實時分析,可以對數(shù)據(jù)進(jìn)行實時查詢,這對于快速檢索數(shù)據(jù)非常有用。
5:可靠性:Elasticsearch具有可靠性和高可用性,支持?jǐn)?shù)據(jù)備份和恢復(fù)。
ES為什么塊:
1:分布式存儲:Elasticsearch使用分布式存儲技術(shù),將數(shù)據(jù)存儲在多個節(jié)點上,從而減少單個節(jié)點的壓力,提高整體性能。
2:索引分片:Elasticsearch把每個索引劃分成多個分片,這樣可以讓查詢操作并行化,從而提高查詢速度。
3:全文索引:Elasticsearch使用了高效的全文索引技術(shù),把文檔轉(zhuǎn)化成可搜索的結(jié)構(gòu)化數(shù)據(jù),使得搜索操作快速高效。
4:倒排索引:Elasticsearch支持倒排索引這種數(shù)據(jù)結(jié)構(gòu),倒排索引將文檔中的每個詞與該詞出現(xiàn)在哪些文檔中進(jìn)行映射,并存儲這些信息。當(dāng)搜索請求發(fā)生時,ES可以快速查找包含所有搜索詞的文檔,從而返回結(jié)果。
5:索引優(yōu)化:Elasticsearch通過索引優(yōu)化技術(shù),可以使查詢速度更快。例如,它支持索引覆蓋、索引下推等優(yōu)化技術(shù),使得查詢速度更快。
6:預(yù)存儲結(jié)果:Elasticsearch在插入數(shù)據(jù)時,對數(shù)據(jù)進(jìn)行預(yù)處理,把結(jié)果預(yù)存儲到索引中,從而在查詢時不需要再重新計算,提高查詢速度。
7:高效的查詢引擎:Elasticsearch使用了高效的查詢引擎,支持各種類型的查詢,并對復(fù)雜查詢提供了優(yōu)化策略,從而提高查詢速度。
8:異步請求處理:ES使用了異步請求處理機制,能夠在請求到達(dá)時立即返回,避免長時間的等待,提高用戶體驗。
9:內(nèi)存存儲:ES使用了內(nèi)存存儲技術(shù),能夠在讀寫數(shù)據(jù)時大大減少磁盤訪問次數(shù),提高數(shù)據(jù)存儲和查詢效率。
我覺得最重要就是倒排索引了:它 用于快速搜索文檔中的某個詞匯。
假設(shè)我們有一個原始文檔:
文檔ID | 文檔內(nèi)容 |
---|---|
Doc1 | "Elasticsearch is fast" |
Doc2 | "Redis is fast too" |
Doc3 | "Elasticsearch and Redis" |
主要分為倆個過程:
分詞(Tokenization):
Doc1 → ["elasticsearch", "is", "fast"]
Doc2 → ["redis", "is", "fast", "too"]
Doc3 → ["elasticsearch", "and", "redis"]
生成詞項-文檔映射:
Term DocIDs (Postings List) ───────────────────────────────────── "and" → [Doc3] "elasticsearch" → [Doc1, Doc3] "fast" → [Doc1, Doc2] "is" → [Doc1, Doc2] "redis" → [Doc2, Doc3] "too" → [Doc2]
2. 倒排索引的核心組件
組件 | 作用 | 示例 |
---|---|---|
詞項字典(Term Dictionary) | 存儲所有唯一詞項,通常用 FST(有限狀態(tài)轉(zhuǎn)換器) 壓縮存儲 | "elasticsearch", "redis" |
倒排列表(Postings List) | 記錄包含該詞項的文檔ID及位置信息(支持快速跳表SkipList優(yōu)化遍歷) | Doc1:[pos1,pos2], Doc3:[pos1] |
詞頻(TF) | 詞項在文檔中的出現(xiàn)次數(shù)(用于相關(guān)性評分) | "fast"在Doc1中TF=1 |
文檔頻率(DF) | 包含該詞項的文檔數(shù)(用于IDF計算) | "elasti |
倒排索引的優(yōu)化技術(shù)
壓縮存儲:
FST:壓縮詞項字典,減少內(nèi)存占用。
Delta Encoding:對文檔ID差值編碼(如[100, 102, 105]→[100, +2, +3])。
跳表(SkipList):
加速倒排列表的合并操作(如
AND
查詢)。
多級索引:
內(nèi)存中保留熱點詞項,磁盤存全量數(shù)據(jù)。
二、Elasticsearch 核心技術(shù)細(xì)節(jié)
1. 分詞器(Analyzer)
分詞器類型 | 功能說明 | 示例 |
---|---|---|
Standard | 默認(rèn)分詞器,按空格/標(biāo)點切分 | "Elasticsearch" → ["elasticsearch"] |
IK Analyzer | 中文分詞(社區(qū)版+擴展詞典) IK分詞器有幾種模式?
IK分詞器如何拓展詞條?如何停用詞條?
| "華為手機" → ["華為", "手機"] |
Pinyin | 中文轉(zhuǎn)拼音搜索 | "北京" → ["beijing", "bj"] |
Whitespace | 僅按空格切分 | "hello world" → ["hello", "world"] |
Keyword | 不分詞,整體作為Term | "2023-08-15" → ["2023-08-15"] |
自定義分詞器:
PUT /my_index { "settings": { "analysis": { "analyzer": { "my_ik": { "type": "custom", "tokenizer": "ik_max_word", "filter": ["lowercase"] } } } } }
2. 底層原理
倒排索引(Inverted Index):
Term → Document ID 的映射(如“手機” → [Doc1, Doc3])。
通過 FST(Finite State Transducer) 壓縮存儲,減少內(nèi)存占用。
分片(Shard)機制:
索引自動拆分為多個分片(默認(rèn)5個),分散到不同節(jié)點。
每個分片有1個主副本和N個從副本(通過
_settings
調(diào)整)。
近實時(NRT):
數(shù)據(jù)寫入后默認(rèn)1秒(
refresh_interval
)可被搜索,通過 translog 保證持久化。
3. 查詢高效的原因
分布式計算:
查詢并行發(fā)送到所有分片,結(jié)果聚合(Scatter-Gather模式)。
緩存優(yōu)化:
Query Cache:緩存過濾條件結(jié)果。
Fielddata:文本字段啟用內(nèi)存緩存(慎用,易OOM)。
列式存儲(Doc Values):
對排序、聚合字段預(yù)先構(gòu)建磁盤數(shù)據(jù)結(jié)構(gòu),避免實時計算。
4. 增刪改操作
寫入流程:
請求發(fā)送到協(xié)調(diào)節(jié)點。
路由到對應(yīng)分片的主副本。
寫入Lucene內(nèi)存Buffer和translog。
定期刷新(Refresh)生成新Segment(可搜索)。
后臺合并(Merge)Segment優(yōu)化存儲。
刪除:
標(biāo)記文檔為
deleted
,Merge時物理刪除。
更新:
先刪除舊文檔,再寫入新文檔(版本號
_version
遞增)。
三、關(guān)鍵問題解決方案
1. 深度分頁優(yōu)化
問題:
from 10000, size 10
需遍歷所有分片的10010條記錄。在Elasticsearch中進(jìn)行分頁查詢通常使用from和size參數(shù)。當(dāng)我們對Elasticsearch發(fā)起一個帶有分頁參數(shù)的查詢(如使用from和size參數(shù))時,ES需要遍歷所有匹配的文檔直到達(dá)到指定的起始點(from),然后返回從這一點開始的size個文檔。跟MySQL的深度分頁原因差不多,方案:
Search After:search_after 是 Elasticsearch 中用于實現(xiàn)深度分頁的一種機制。與傳統(tǒng)的分頁方法(使用 from 和 size 參數(shù))不同,search_after 允許你基于上一次查詢的結(jié)果來獲取下一批數(shù)據(jù),這在處理大量數(shù)據(jù)時特別有效。
在第一次查詢時,你需要定義一個排序規(guī)則。不需要指定 search_after 參數(shù):{ "query": { "match_all": {} }, "size": 10, "sort": [{"_id": "asc"}],//在第一次查詢時,你需要定義一個排序規(guī)則。 "search_after": [last_id] //第一次查詢不要定義,在后續(xù)的查詢中,使用上一次查詢結(jié)果中最后一條記錄的排序值 //search_after包含timestamp和last_id 的值,對應(yīng)上一次查詢結(jié)果的最后一條記錄。 }
search_after 可以有效解決深度分頁問題,原因如下:
避免重復(fù)處理數(shù)據(jù):與傳統(tǒng)的分頁方式不同,search_after 不需要處理每個分頁請求中所有先前頁面上的數(shù)據(jù)。這大大減少了處理數(shù)據(jù)的工作量。
提高查詢效率:由于不需要重復(fù)計算和跳過大量先前頁面上的數(shù)據(jù),search_after 方法能顯著提高查詢效率,尤其是在訪問數(shù)據(jù)集靠后部分的數(shù)據(jù)時。
但是這個方案有一些局限,一方面需要有一個全局唯一的字段用來排序,另外雖然一次分頁查詢時不需要處理先前頁面中的數(shù)據(jù),但實際需要依賴上一個頁面中的查詢結(jié)果。適用于深度分頁和大數(shù)據(jù)集的遍歷。
Scroll API:Scroll API在Elasticsearch中的主要目的是為了能夠遍歷大量的數(shù)據(jù),它通常用于數(shù)據(jù)導(dǎo)出或者進(jìn)行大規(guī)模的數(shù)據(jù)分析??梢杂糜谔幚泶罅繑?shù)據(jù)的深度分頁問題。
POST /_search/scroll { "scroll": "1m", "scroll_id": "DXF1ZXJ5QW..." } //如上方式初始化一個帶有scroll參數(shù)的搜索請求。這個請求返回一個scroll ID,用于后續(xù)的滾動。Scroll參數(shù)指定了scroll的有效期,例如1m表示一分鐘。 //接下來就可以使用返回的scroll ID來獲取下一批數(shù)據(jù)。每次請求也會更新scroll ID的有效期。
業(yè)務(wù)妥協(xié):限制最大頁碼(如只展示前100頁)。
避免重復(fù)排序:在傳統(tǒng)的分頁方式中,每次分頁請求都需要對所有匹配的數(shù)據(jù)進(jìn)行排序,以確定分頁的起點。Scroll避免了這種重復(fù)排序,因為它保持了一個游標(biāo)。
穩(wěn)定視圖:Scroll提供了對數(shù)據(jù)的“穩(wěn)定視圖”。當(dāng)你開始一個scroll時,Elasticsearch會保持搜索時刻的數(shù)據(jù)快照,這意味著即使數(shù)據(jù)隨后被修改,返回的結(jié)果仍然是一致的。
減少資源消耗:
由于不需要重復(fù)排序,Scroll減少了對CPU和內(nèi)存的消耗,特別是對于大數(shù)據(jù)集。Scroll非常適合于處理需要訪問大量數(shù)據(jù)但不需要快速響應(yīng)的場景,如數(shù)據(jù)導(dǎo)出、備份或大規(guī)模數(shù)據(jù)分析。
但是,需要知道,使用Scroll API進(jìn)行分頁并不高效,因為你需要先獲取所有前面頁的數(shù)據(jù)。Scroll API主要用于遍歷整個索引或大量數(shù)據(jù),而不是用于快速訪問特定頁數(shù)的數(shù)據(jù)。
2. 數(shù)據(jù)一致性
第一種方法:雙寫一致性
對MySQL和ES進(jìn)行雙寫,先更新數(shù)據(jù)庫,再更新ES,放在一個事務(wù)里面,需要保證事務(wù)的一致性。有數(shù)據(jù)不一致的風(fēng)險,比如MySQL寫入成功,但是ES發(fā)生了寫入成功但因為超時拋異常了就會出現(xiàn)數(shù)據(jù)不一致的情況。
第二種方法:使用消息隊列MQ進(jìn)行處理
在更新數(shù)據(jù)庫時,發(fā)送一個消息到MQ中,然后數(shù)據(jù)庫和ES各設(shè)置一個監(jiān)聽者,監(jiān)聽消息之后各自去做數(shù)據(jù)變更,如果失敗了就基于消息的重試在重新執(zhí)行。
好處是進(jìn)行了異步解耦,性能稍后,但是有延遲
第三種方法:定時掃描MySQL
如果ES中的數(shù)據(jù)變更的實時性要求不高,可以考慮定時任務(wù)掃表來批量更新ES。
這個方案優(yōu)點是沒有侵入性,數(shù)據(jù)庫的寫操作處不需要改代碼。
缺點是實時性很差,并且輪詢可能存在性能問題、效率問題以及給數(shù)據(jù)庫帶來壓力。
第四種方法:監(jiān)聽binlog日志(基于canal做數(shù)據(jù)同步的方案)
對業(yè)務(wù)代碼完全沒有侵入性,業(yè)務(wù)也非常解耦,不需要關(guān)心這個ES的更新操作。
缺點就是需要基于binlog監(jiān)聽,需要引入第三方框架。存在一定的延遲。
一致性級別 | 實現(xiàn)方案 | 優(yōu)缺點 |
---|---|---|
強一致性 | 寫入后立即refresh (性能差) | 數(shù)據(jù)最新,吞吐量下降 |
最終一致性 | 默認(rèn)1秒刷新 + 手動_refresh (平衡選擇) | 性能高,短暫延遲 |
與Canal集成:主要的過程
MySQL Binlog → Canal Server 解析變更。
Canal Client → Kafka 發(fā)送變更事件。
Logstash/自定義Consumer → 寫入ES。
關(guān)于Logstash和自定義Consumer
. Logstash 是什么?
定位:開源的數(shù)據(jù)處理管道工具,屬于 Elastic Stack(ELK)的一部分。
核心功能:
數(shù)據(jù)輸入(Input):從 Kafka、MySQL、文件等讀取數(shù)據(jù)。
數(shù)據(jù)過濾(Filter):清洗、轉(zhuǎn)換、豐富數(shù)據(jù)(如字段重命名、類型轉(zhuǎn)換)。
數(shù)據(jù)輸出(Output):將處理后的數(shù)據(jù)寫入 ES、MySQL、文件等。
特點:
配置驅(qū)動:通過配置文件定義數(shù)據(jù)處理流程,無需編碼。
插件化:支持 200+ 官方/社區(qū)插件(如
kafka
、elasticsearch
、grok
)。
Canal → ES 場景中的用途
將 Canal 發(fā)送到 Kafka 的 MySQL Binlog 數(shù)據(jù)轉(zhuǎn)換為 ES 所需的格式,并寫入 ES。
自定義 Consumer 是什么?
定位:用戶自行編寫的程序(通常用 Java/Python/Go),用于消費 Kafka 消息并處理。
核心功能:
從 Kafka 拉取 Canal 生成的 Binlog 消息。
解析消息并轉(zhuǎn)換為 ES 支持的格式(如 JSON)。
調(diào)用 ES 的 API 寫入數(shù)據(jù)。
特點:
靈活可控:可自定義業(yè)務(wù)邏輯(如特殊字段處理、錯誤重試)。
高性能:通過批量寫入、異步請求等優(yōu)化吞吐量。
整體架構(gòu)流程:
3. ES支持的數(shù)據(jù)結(jié)構(gòu)
核心類型:
Text:用于存儲全文文本數(shù)據(jù)。
Keyword:用于存儲文本值,通常用于索引結(jié)構(gòu)化內(nèi)容,如郵件地址、標(biāo)簽或任何需要精確匹配的內(nèi)容。
Nested:類似于 Object 類型,但用于存儲數(shù)組列表,其中列表中的每個元素都是完全獨立且可搜索的。
Long, Integer, Short, Byte, Double, Float: 這些是數(shù)值類型,用于存儲各種形式的數(shù)字。
Date: 存儲日期或日期和時間。
Boolean: 存儲 true 或 false 值。
Binary: 用于存儲二進(jìn)制數(shù)據(jù)。
Object: 用于嵌套文檔,即文檔內(nèi)部可以包含文檔。
特殊類型:
Flattened:避免深層JSON字段爆炸。
Join:父子文檔(性能較差,慎用)。
text 和 keyword 有啥區(qū)別?
text 類型被設(shè)計用于全文搜索。這意味著當(dāng)文本被存儲為 text 類型時,Elasticsearch 會對其進(jìn)行分詞,把文本分解成單獨的詞或短語,便于搜索引擎進(jìn)行全文搜索。因為 text 字段經(jīng)過分詞,它不適合用于排序或聚合查詢。
text適用于存儲需要進(jìn)行全文搜索的內(nèi)容,比如新聞文章、產(chǎn)品描述等。
keyword 類型用于精確值匹配,不進(jìn)行分詞處理。這意味著存儲在 keyword 字段的文本會被當(dāng)作一個完整不可分割的單元進(jìn)行處理。因為 keyword 類型字段是作為整體存儲,它們非常適合用于聚合(如計數(shù)、求和、過濾唯一值等)和排序操作。由于不進(jìn)行分詞,keyword 類型字段不支持全文搜索,但可以進(jìn)行精確匹配查詢。
keyword適用于需要進(jìn)行精確搜索的場景,比如標(biāo)簽、ID 編號、郵箱地址等。ES 不支持 decimal,如何避免丟失精度?
五種方法:
一:使用字符串類型(比較好用)
完全保留數(shù)字的精度。簡單易于實現(xiàn),數(shù)據(jù)遷移時不需特別處理。但是作為字符串存儲的數(shù)字不能直接用于數(shù)值比較或數(shù)學(xué)運算,需要在應(yīng)用層處理轉(zhuǎn)換。但也不是什么大毛病。
二:擴大浮點類型的精度
就是直接使用 double 類型,在理論上可能會有精度損失,但實際上 double 類型提供的精度對于許多業(yè)務(wù)需求已經(jīng)足夠使用。需要接受減小精度損失。
三:使用scaled_float(推薦)
Elasticsearch 的 scaled_float 類型是一種數(shù)值數(shù)據(jù)類型,專門用于存儲浮點數(shù)。其特點是通過一個縮放因子(scaling factor)將浮點數(shù)轉(zhuǎn)換為整數(shù)來存儲,從而在一定范圍內(nèi)提高存儲和計算的效率。他使用一個縮放因子將浮點數(shù)轉(zhuǎn)換為整數(shù)存儲。例如,如果縮放因子是 100,那么值 123.45 會存儲為 12345。這樣可以避免浮點數(shù)存儲和計算中的精度問題。
四:使用多個字段
在某些情況下,可以將 decimal 數(shù)值拆分為兩個字段存儲:一個為整數(shù)部分,另一個為小數(shù)部分。這樣做可以在不丟失精度的情況下,將數(shù)值分開處理。可以保持?jǐn)?shù)值精確,同時可進(jìn)行部分?jǐn)?shù)學(xué)運算。但是增加了數(shù)據(jù)處理的復(fù)雜性,需要在應(yīng)用層重建數(shù)值。
五:使用自定義腳本
用 Elasticsearch 的腳本功能(如 Painless 腳本)來處理數(shù)值計算,確保在處理過程中控制精度。優(yōu)點:靈活控制數(shù)據(jù)處理邏輯。缺點:可能影響查詢性能,增加系統(tǒng)復(fù)雜性。
四、實際應(yīng)用場景
1. 電商搜索
需求:支持顏色、品牌、價格區(qū)間等多維度過濾。
實現(xiàn):
{ "query": { "bool": { "must": [ { "term": { "brand": "華為" } }, { "range": { "price": { "gte": 1000, "lte": 2000 } } } ], "filter": { "term": { "color": "紅色" } } } }, "aggs": { "price_stats": { "stats": { "field": "price" } } } }
2. 日志告警
需求:實時檢測ERROR日志并觸發(fā)告警。
實現(xiàn):
Watcher 插件定時查詢:
{ "query": { "match": { "level": "ERROR" } }, "condition": { "compare": { "ctx.hits.total": { "gt": 0 } } }, "actions": { "email": { "to": "admin@example.com" } } }
3. 數(shù)據(jù)同步容災(zāi)
雙寫方案:
應(yīng)用同時寫MySQL和ES,通過本地事務(wù)表記錄同步狀態(tài)。
補償機制:
定時任務(wù)掃描MySQL與ES差異數(shù)據(jù),修復(fù)不一致。
五、性能調(diào)優(yōu)
集群和硬件優(yōu)化
負(fù)載均衡: 確保查詢負(fù)載在集群中均衡分配。
硬件資源: 根據(jù)需要增加 CPU、內(nèi)存或改善 I/O 性能(例如使用 SSD)。
配置 JVM: 優(yōu)化 JVM 設(shè)置,如堆大小,以提高性能。
硬件:SSD磁盤、32GB+內(nèi)存(堆內(nèi)存不超過31GB)。
索引設(shè)計:
選擇合適的分詞器
冷熱分離:hot-warm
架構(gòu)(熱數(shù)據(jù)用SSD,冷數(shù)據(jù)用HDD)。生命周期管理(ILM):自動滾動到新索引。
查詢優(yōu)化:
避免
wildcard、
regexp查詢(如*test*
)。使用
constant_score
過濾不相關(guān)文檔。使用過濾器: 對于不需要評分的查詢條件,使用 filter 而不是 query,因為 filter 可以被緩存以加快后續(xù)相同查詢的速度。
合理使用聚合:聚合可以用于高效地進(jìn)行數(shù)據(jù)分析,但復(fù)雜的聚合也可能非常消耗資源。優(yōu)化聚合查詢,如通過限制桶的數(shù)量,避免過度復(fù)雜的嵌套聚合。
查詢盡可能少的字段: 只返回查詢中需要的字段,減少數(shù)據(jù)傳輸和處理時間。
避免深度分頁: 避免深度分頁,對于需要處理大量數(shù)據(jù)的情況,考慮使用 search_after。
總結(jié)
選型:ES適合搜索/分析,MySQL適合事務(wù)/精準(zhǔn)查詢。
核心能力:分詞器、倒排索引、分布式計算支撐高效查詢。
一致性:通過
refresh
、Canal同步等方案平衡實時性與性能。實踐:結(jié)合業(yè)務(wù)場景選擇分頁策略、數(shù)據(jù)結(jié)構(gòu)、同步機制。
到此這篇關(guān)于為什么用ElasticSearch以及和傳統(tǒng)數(shù)據(jù)庫MySQL有什么區(qū)別的文章就介紹到這了,更多相關(guān)es和mysql對比內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis動態(tài)調(diào)用表名和字段名的解決方法
今天在項目開發(fā)中有個業(yè)務(wù)是需要限制各個用戶對某些表里的字段查詢以及某些字段是否顯示,這種情況下,就需要構(gòu)建sql來動態(tài)傳入表名、字段名了,下面給大家介紹mybatis動態(tài)調(diào)用表名和字段名的解決方法,一起看看吧2016-10-10Spring @Cacheable redis異常不影響正常業(yè)務(wù)方案
這篇文章主要介紹了Spring @Cacheable redis異常不影響正常業(yè)務(wù)方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02Spring 應(yīng)用中集成 Apache Shiro的方法
這篇文章主要介紹了Spring 應(yīng)用中集成 Apache Shiro的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05Spring集成webSocket頁面訪問404問題的解決方法
這篇文章主要介紹了Spring集成webSocket頁面訪問404問題的解決方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12