1. 程式人生 > >財務平臺億級資料量毫秒級查詢優化之elasticsearch原理解析

財務平臺億級資料量毫秒級查詢優化之elasticsearch原理解析

財務平臺進行分錄分表以後,隨著資料量的日漸遞增,業務人員對賬務資料的實時分析響應時間越來越長,體驗性慢慢下降,之前我們基於mysql的效能優化做了一遍,可以說基於mysql該做的優化已經基本上都做了,本次是基於elasticsearch對其做進一步的效能優化

正文
1mysql索引原理

基於mysql最常用也最直接有效的效能優化也就是新增索引。

mysql索引是怎麼實現的呢?資料庫最基本的查詢演算法是順序查詢,時間複雜度為O(n),顯然在資料量很大的時候很低,優化的查詢演算法有二分查詢,二叉樹查詢,雖然查詢效率提高了,但是各自對檢索的資料都有要求,二分查詢檢索被要求資料是有序的,而二叉樹查詢只能用於二叉樹上,但是資料本身的組織結構不可能完全滿足各種資料結構,例如,理論上不可能同時將兩列都按順序進行組織,所以在資料之外,資料庫系統還維護者滿足特定查詢演算法的資料結構,這些資料結構以某種方式引用資料,這樣就可以在這些資料結構上實現高階查詢演算法,這種資料結構就是索引。

索引是什麼?索引是儲存引擎用於快速找到記錄的一種資料結構,這是索引的基本功能,主要基於hash,b+tree。

我們開發當中一般用到都是mysql innoDB引擎,採用的是b+tree。

b+tree的優勢主要體現在查詢效能上,在單元素查詢時,b+tree會自頂層向下逐層查詢節點,最終找到我們需要的葉子節點,範圍查詢時,b+tree找到葉子節點的起始位置,通過葉子節點連結串列依次查詢資料,直到範圍結束為止。
這裡寫圖片描述

參考上面的示意圖

總結:基於b+tree的mysql索引,當這個樹的形狀瘦低的時候查詢效率就會很快,因為查詢磁碟的io次數很少,但是如果這個樹的形狀胖高的時候,查詢磁碟的次數就會比較多,那麼查詢效率就會越來越慢,所以基於mysql索引的效能優化,索引是有限制的,適量的新增索引會對查詢效率有明顯提升,但是索引過量就適得其反,不但查詢效率會降低,也會影響其他操作的效率,因為其他操作的時候也是需要維護索引的。

1elasticsearch索引原理

elasticsearch底層是索引原理是倒排索引,使用場景一般是OLAP,支援rest風格json資料格式互動的全文檢索引擎,開源,面向文件設計,實時檢索,索引可以無限擴充套件,只要你的伺服器的磁碟、記憶體足夠大。

我們先看一個列子
這裡寫圖片描述

一個欄位有一個自己的倒排索引。18,20這些叫做term,而[1,3]就是postinglist。Posting list就是一個int的陣列,儲存了所有符合某個term的文件id。

term Dictionary
term排序後的集合,方便二分查詢,有了term Dictionary之後就可以在磁碟上查詢到具體的document,磁碟的讀操作非常昂貴,一次大概需要10ms時間,不同儲存方式的磁碟效能不一樣,所以為了減少磁碟的讀取次數就必要把一些資料快取到記憶體中,但是term Dictionary會有很多,不能完整的放到記憶體中,於是就有了termindex
term index
可以理解為就是英文詞典的目錄,它是一棵樹的結構

示意圖
這裡寫圖片描述

這棵樹不會包含所有的term,它只包含term的一些字首,通過term index可以快速地定位到term dictionary的某個offset,然後從這個位置再往後順序查詢,大大減少了磁碟訪問次數

示意圖
這裡寫圖片描述

所以term index不需要存下所有的term,而僅僅是他們的一些字首與Term Dictionary的block之間的對映關係,再結合FST(Finite StateTransducers)的壓縮技術,可以使term index快取到記憶體中
為什麼elasticsearch比mysql快
mysql只有 termdictionary這一層,是以樹的方式儲存在磁碟上的。檢索一個term需要若干次的磁碟訪問操作,而elasticsearch,在term dictionary的基礎上添加了term index來加速檢索,term index以樹的形式快取在記憶體中。從term index查到對應的term dictionary的block位置之後,再去磁碟上找term,大大減少了磁碟的訪問次數。
term index在記憶體中是以FST的形式儲存的,其特點是非常節省記憶體。Term dictionary在磁碟上是以分block的方式儲存的,一個block內部利用公共字首壓縮,比如都是Ab開頭的單詞就可以把Ab省去。這樣term dictionary可以更節約磁碟空間。
壓縮技術
用FST壓縮term index之外,對posting list也有壓縮。

聯合索引查詢
以上都是單field索引,如果多個field索引的聯合查詢,比如查詢age=18 AND gender=女,倒排索引如何滿足快速查詢的要求呢?大致過程如下:根據過濾條件 age=18 的先從term index找到18在term dictionary的大概位置,然後再從term dictionary裡精確地找到18這個term,然後得到一個posting list或者一個指向posting list位置的指標。然後再查詢gender=女的過程也是類似的。最後得出age=18 AND gender=女,就是把兩個 posting list做一個“與”的合併
1、skip list
2、bitset 二進位制,直接按位與
總結
elasticsearch就是儘量將磁盤裡的東西搬進記憶體,減少磁碟隨機讀取次數(同時也利用磁碟順序讀特性),結合各種壓縮演算法,高效使用記憶體,從而達到快速搜尋的目的。

1mysql索引與elasticsearch索引對比

mysql
如果資料量不是特別大,在千萬級別,適當的管理好索引,查詢效率還是可以的,但是對索引命中率有要求,就是必須要保證索引的命中率,還有就是索引的數量限制好,但是查詢條件比較多、需要新增很多索引的時候mysql索引就有瓶頸了。

elasticsearch
使用了OLAP場景,海量資料實時查詢,億級以上資料量,因為底層採用的是倒排索引機制,只要你的伺服器資源足夠好,理論上隨著資料量的增加、索引的增量,實時查詢效率是線性的。

倒排索引
倒排索引應用場景:搜尋引擎、實時排名,如百度搜索,搜狗搜尋
索引分為正向索引和反向索引(倒排索引)
正向索引:通過Key找Value
正向索引的結構如下:

   “文件1”的ID > 單詞1:出現次數,出現位置列表;單詞2:出現次數,出現位置列表;…………。

   “文件2”的ID > 此文件出現的關鍵詞列表。

倒排索引:通過Value找Key
倒排索引的結構如下:

   “關鍵詞1”:“文件1”的ID,“文件2”的ID,…………。

   “關鍵詞2”:帶有此關鍵詞的文件ID列表。

對應的倒排列表為:{(3;1;<4>),(5;1;<4>)},其含義為在文件3和文件5出現過這個單詞,單詞頻率都為1,單詞“拉斯”在兩個文件中的出現位置都是4,即文件中第四個單詞是“拉斯”。
倒排索引可以統計文件ID,出現次數,出現位置。