ElasticSearch爲何查詢速度快(秒懂)

有一位學長突然問我你知道爲啥es比數據庫mysql查詢的快嗎?之前對於es的印象就是高效的搜索框架,實際應用過,但是沒想過原理,後來查了一些資料,現在做一下總結。

希望還是小夥伴們可以瞭解一些es的知識之後再來看這一個文章吧。

es爲何查詢速度快?

es採用的是倒序索引,這種索引方式和我們的正常索引不太一樣,我們以一張表來說明,看一下對比:

id age sex name
1 18 female 北大
2 20 male 河北大學青年
3 18 male 愛國青年

在mysql中,是以id簡歷b+樹索引,然後通過目錄頁對應到數據頁,然後找到數據。對於傳統的增刪改查(用id)沒有任何問題,速度也很快,但是對於全文檢索來說,就很尷尬。比如查詢like %北大%。這樣是走不到索引的,需要全表掃描。但是對於es來說,這就好辦多了。

倒序索引:以name爲倒序索引來看。

我們是將內容進行了分詞(這裏是最細粒劃分)。然後指向了我們document的一個唯一的標識,能夠找到位置的地址。

這樣,當我們在程序發出一個查詢請求後,比如“北大青年”。首先會把這個查詢內容分詞:“北大”、“青年”。然後就找到對應的數據[1,2,3]。這三條數據了,比我們在mysql中模糊查詢快的多。這是其中的一個原因。

我們將“北大”、“河北”、“大學...這樣的叫做term。如果有很多個term,那麼我們如何找到對應的term呢。我們以term是英文爲例:假如有Carla,Sara,Elin,Ada,Patty,Kate,Selena。

第一個方法:遍歷?遍歷是不可能遍歷的,這輩子都不可能遍歷的。

第二個方法:採用二分查找(悄悄的告訴你,mysql的inndb中在目錄頁的查找過程中和數據頁的查找對應的數據中均有體現)可以用 logN 次磁盤查找得到目標。但是磁盤的隨機讀操作仍然是非常昂貴的(一次random access大概需要10ms的時間)。而相比於mysql,term的dictionary要大得多。無法完整地放到內存裏,於是就有了第三個方法。

第二個方法:term index。term index有點像一本字典的大的章節表。如果所有的term都是英文字符的話,可能這個term index就真的是26個英文字符表構成的了。但是實際的情況是,term未必都是英文字符,term可以是任意的byte數組。而且26個英文字符也未必是每一個字符都有均等的term,比如x字符開頭的term可能一個都沒有,而s開頭的term又特別多。實際的term index是一棵trie 樹:

這裏只考慮前綴並不考慮完整的分詞字,例子是一個包含 "A", "to", "tea", "ted", "ten", "i", "in", 和 "inn" 的 trie 樹。這棵樹不會包含所有的term,它包含的是term的一些前綴。通過term index可以快速地定位到term dictionary的某個offset,然後從這個位置再往後順序查找。再加上一些壓縮技術(搜索 Lucene Finite State Transducers) term index 的尺寸可以只有所有term的尺寸的幾十分之一,使得用內存緩存整個term index變成可能。整體上來說就是這樣的效果。

這種方式就很快就能夠查找到對應的分詞,然後在對應的分詞就找到了對應的主鍵,然後就可以直接找到對應的數據了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章