摘要:ES已經成爲了全能型的數據產品,在不少領域愈來愈受歡迎,本文旨在從數據庫領域分析ES的使用。
本文分享自華爲雲社區《Elasticsearch數據庫加速實踐》,原文做者:css_blog 。css
1、方案說明
Elasticsearch主要功能是什麼,不一樣的場景有不一樣的定位,在日誌場景咱們能夠用ELK生態搭建日誌分析系統,在搜索領域ES是當前最熱門的搜索引擎。在大數據領域,ES能夠對標Hbase提供海量日誌的數據倉庫;在數據庫領域ES能夠做爲查詢分析型的分析型數據庫使用。ES已經成爲了全能型的數據產品,在不少領域愈來愈受歡迎,本文旨在從數據庫領域分析ES的使用。sql
ES不是關係型數據庫,數據更新採用樂觀鎖,經過版本號控制,不支持事務處理,這也是ES區別於傳統數據庫(Mysql)的地方;可是ES支持精確查詢加速,多條件任意組合查詢,多種聚合查詢,查詢速度很快,能夠替代數據庫複雜條件查詢的場景需求,甚至能夠代替數據庫作二級索引。數據庫
在數據庫加速場景一般的作法是客戶產生的商品訂單數據會寫入Mysql類關係型數據庫,數據庫寫入保證事務性,可是隨着商品訂單的數據愈來愈多,同時客戶查詢的條件多變,沒法全部字段都創建索引,數據庫的查詢能力遠遠不能知足查詢訴求。咱們考慮用ES全量同步數據庫數據,在ES中作多條件聚合查詢,查詢的結果能夠在Mysql中作關聯搜索,在查詢商品訂單詳情展現, Mysql數據和ES數據能夠不要求實時一致,能夠通canal消費Mysql binlog日誌信息, 同步到ES,實現一次寫入,保證數據一致性。如下數據庫都以Mysql爲例進行說明。網絡
2、索引原理分析
ES爲何查詢能力遠遠超過Mysql關係型數據庫,主要是他們的實現原理和底層存儲的數據結構差別決定的,如下比較兩種產品的實現原理。數據結構
Elasticsearch會對全部輸入的文本進行處理,創建索引放入內存中,從而提升搜索效率。在這一點上ES要優於MySQL的B+樹的結構,MySQL須要將索引放入磁盤,每次讀取須要先從磁盤讀取索引而後尋找對應的數據節點,可是ES可以直接在內存中就找到目標文檔對應的大體位置,最大化提升效率。而且在進行組合查詢的時候MySQL的劣勢更加明顯,它不支持複雜的組合查詢好比聚合操做,即便要組合查詢也要事先建好索引,可是ES就能夠完成這種複雜的操做,默認每一個字段都是有索引的,在查詢的時候能夠各類互相組合。架構
(1)數據庫索引B+樹
數據庫中索引都是以樹來組織的,經常使用的有B tree,B-tree,B+tree,如下介紹B+tree的組織結構。併發
首先咱們先想象下爲何須要創建索引,假設咱們有一張表book,存儲了咱們保持的書籍信息,名稱,做者,發佈時間等,咱們有10000條記錄,若是咱們須要找一本爲《database》的書,那咱們的SQL爲:app
select name,author form book where name = ‘database’;
咱們須要掃描整個表,全量比較才能夠,若是咱們對name創建索引,書名已經按照順序排序,查詢時只須要找到對應位置就能夠快速獲取結果。分佈式
索引的本質是經過不斷地縮小想要獲取數據的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,咱們能夠老是用同一種查找方式來鎖定數據。性能
數據庫採用B+tree創建索引:
B+tree 數據只存儲在葉子節點中。這樣在B樹的基礎上每一個節點存儲的關鍵字數更多,樹的層級更少因此查詢數據更快,全部指關鍵字指針都存在葉子節點,因此每次查找的次數都相同因此查詢速度更穩定。
(2)Elasticsearch索引原理
ES創建索引採用倒排索引的方式存儲。
對輸入的全部數據都創建索引,而且把全部和文檔對應起來,在咱們查找數據的時候咱們直接查找詞典(Term),在找到Term對應的文檔ID,進而找到數據。這和Mysql使用B+tree樹創建索引的方式相似,可是若是詞典Term很大,對Term的搜索就會很慢,ES進一步建議了詞典索引(FST),提高詞典的搜索能力。
Term Index 以樹的形式保存在內存中,運用了FST+壓縮公共前綴方法極大的節省了內存,經過Term Index查詢到Term Dictionary所在的block再去磁盤上找term減小了IO次數。
Term Dictionary 排序後經過二分法將檢索的時間複雜度從原來N下降爲logN。
3、查詢對比分析
如下對於數據庫搜索經常使用的場景對比ES和數據庫:
- 全文檢索
ES支持全文檢索,能夠對數據分詞,每一個詞經過FSP創建詞典索引,而Mysql關係數據庫則不支持,想象下若是搜索的不是整個字段而是字段中的幾個關鍵詞,使用Mysql搜索必須全表掃描。
- 精確搜索
若是Mysql對該字段創建過索引,使用ES搜索和Mysql搜索性能差別不大,可能Mysql更快點,可是ES是分佈式系統,能夠支持PB級別的數據搜索,對大表搜索ES優點更明顯。
- 多條件查詢
咱們知道Mysql須要對字段創建索引才能加速搜索過程,而ES默認是全索引的,對於多條件查詢,觸發Mysql創建聯合索引,不然多個字段搜索,Mysql 先選擇一個字段搜索,結果在使用第二個字段過濾獲得最終結果。
ES則採用多個字段結果集交併操做,使用bitmap或者skiplist加快搜索速度,相比Mysql優點明顯。
- 聚合搜索
Mysql聚合搜索若是沒有創建索引須要全表掃描排序,若是創建索引在B+tree上進行範圍查詢。
ES爲了加快聚合搜索速度,經過Doc value來解決聚合搜索問題。DocValue就是列式存儲。
存儲結果以下:
Docvalue數據按照文檔ID排序,DocValue將隨機讀取變成了順序讀取,
在es中,由於分片的存在,數據被拆分紅多份,放在不一樣機器上。可是給用戶體驗卻好像只有一個庫同樣。對於聚合查詢,其處理是分兩階段完成的:
- Shard 本地的 Lucene Index 並行計算出局部的聚合結果。
- 收到全部的 Shard 的局部聚合結果,聚合出最終的聚合結果。
這種兩階段聚合的架構使得每一個 shard 不用把原數據返回,而只用返回數據量小得多的聚合結果。這樣極大的減小了網絡帶寬的消耗。
- 多副本加速
咱們知道ES有shard和replica的概念,副本一方面能夠保證數據的可靠性,另外一方面多副本能夠加快搜索速度提升搜索併發能力。
4、數據庫到Elasticsearch同步方案
結合用戶實際的使用方式和數據量的大小,Mysql數據到ES能夠有多種不一樣的方式選擇。
- Canal=>Elasticsearch
使用Canal直接消費Mysql binlog日誌寫入ES,這種方式若是Mysql寫入量大,會面臨Canal寫入阻塞問題。
- Canal =>Kafka=>Elasticsearch
Canal數據寫入到Kafka,使用另外的app消費Kafka數據同步到ES
5、問題彙總
1.索引shard問題
在Mysql數據同步到ES中面臨索引的創建的問題,在數據寫入ES以前咱們須要提早規劃數據的shards和replicas的個數,replicas 能夠動態修改,可是shards數建立完成後不能修改。
隨着Mysql數據量的增長,若是shard太少,就會致使每一個shard的數據量太大的問題。
若是一個索引600G,只有3 個shard,每一個shard就200G,會極大的損耗查詢能力,也不利於數據遷移。
咱們能夠按照月來滾動建立索引,經過索引別名把全部索引關聯起來使用。
test_data-202101 test_data-202102
2.查詢加速問題
在使用ES對數據庫進行加速的場景,咱們但願的是ES查詢能力盡量快。在ES查詢不知足要求的時候咱們須要對查詢進行調優。
經常使用的方法有: