什么是ES

整體理解的索引召回結(jié)構(gòu):段(segment文件)-詞項(xiàng)索引(FST內(nèi)存)- 找到詞典可能所在的塊 - 詞典(字典序文件)、倒排表(posting list文件、跳表查找)-bool運(yùn)算
https://blog.csdn.net/weixin_38289303/article/details/109399137

倒排查詢邏輯
在介紹了索引表和記錄表的結(jié)構(gòu)后,就可以得到 Lucene 倒排索引的查詢步驟:
通過 Term Index 數(shù)據(jù)(.tip文件)中的 StartFP 獲取指定字段的 FST通過 FST 找到指定 Term 在 Term Dictionary(.tim 文件)可能存在的 Block將對應(yīng) Block 加載內(nèi)存,遍歷 Block 中的 Entry,通過后綴(Suffix)判斷是否存在指定 Term存在則通過 Entry 的 TermStat 數(shù)據(jù)中各個(gè)文件的 FP 獲取 Posting 數(shù)據(jù)如果需要獲取 Term 對應(yīng)的所有 DocId 則直接遍歷 TermFreqs,如果獲取指定 DocId 數(shù)據(jù)則通過 SkipData 快速跳轉(zhuǎn)

Term Dictionary(簡單理解:field字典)
例如字典序排序之后就變成了:
Ada,Carla,Elin,Kate,Patty,Sara,Selena
這樣我們可以用二分查找的方式,比全遍歷更快地找出目標(biāo)的 term。這個(gè)就是 term dictionary。有了 term dictionary 之后,可以用 logN 次磁盤查找得到目標(biāo)。

Term Index倒排詞典的索引是常駐內(nèi)存的

想想為啥不用 HashMap,HashMap 也能實(shí)現(xiàn)有序Map?耗內(nèi)存??!犧牲了一點(diǎn)性能來節(jié)約內(nèi)存,旨在把所有Term Index都放在內(nèi)存里面,最終的效果是提升了速度,否則hashmap無法支持各種分詞后的模糊搜索。如上可知,F(xiàn)ST是壓縮字典樹后綴的圖結(jié)構(gòu),她擁有Trie高效搜索能力,同時(shí)還非常小。這樣的話我們的搜索時(shí),能把整個(gè)FST加載到內(nèi)存。

“為什么 Elasticsearch/Lucene 檢索可以比 mysql 快“。Mysql 只有 term dictionary 這一層,是以 b-tree 排序的方式存儲在磁盤上的。檢索一個(gè) term 需要若干次的 random access 的磁盤操作。而 Lucene 在 term dictionary 的基礎(chǔ)上添加了 term index 來加速檢索,term index 以樹的形式緩存在內(nèi)存中。從 term index 查到對應(yīng)的 term dictionary 的 block 位置之后,再去磁盤上找 term,大大減少了磁盤的 random access 次數(shù)。

image.png

每個(gè)節(jié)點(diǎn)表示一個(gè)ES進(jìn)程(通常每個(gè)節(jié)點(diǎn)部署獨(dú)立機(jī)器),每個(gè)分片表示一個(gè)lucene實(shí)例。當(dāng)節(jié)點(diǎn)數(shù)發(fā)生變化(擴(kuò)容、縮容)時(shí),會(huì)觸發(fā)分片rebalance。


image.png

os cache即文件系統(tǒng)緩存,是屬于內(nèi)存的。segment(包含倒排索引+正排索引)refresh到os cache后就可以被檢索,但需要flush到磁盤才持久化。
Translog 的刷盤方式有兩種:同步(request)和異步(async)
ES 默認(rèn)使用的是 request,即每次寫入、更新、刪除操作后立刻執(zhí)行 fsync 落盤。
如果使用異步的方式,則根據(jù)同步間隔周期性(通常是5s)的刷盤。


image.png

image.png

image.png

數(shù)據(jù)寫入:在主分片節(jié)點(diǎn)上,數(shù)據(jù)會(huì)先被寫入(index buffer)中,同時(shí)寫入 translog,這個(gè)時(shí)候數(shù)據(jù)還不能被搜索到(這個(gè)也是 es 是近實(shí)時(shí)搜索的原因);

tips:整個(gè)過程大部分在內(nèi)存中,如果斷電就會(huì)導(dǎo)致數(shù)據(jù)丟失。因此,ES 引入了 translog,數(shù)據(jù)寫入內(nèi)存時(shí),會(huì)同時(shí)寫入 translog(會(huì)立即落盤),來保證數(shù)據(jù)不丟失。

4、經(jīng)過一段時(shí)間(默認(rèn) 1s)或者 index buffer 滿了(默認(rèn) jvm 的 10%),會(huì)將 index buffer 中的文檔 refresh 到系統(tǒng)文件緩存(os cache),然后再刷入到 lucene 的底層文件 segment 中,同時(shí)建立倒排索引,這個(gè)時(shí)候文檔是可以被搜索到的;

5、 由于 segment 的不可變性,隨著 segment 越來越多,每打開一個(gè) segment 就會(huì)消耗一個(gè)文件句柄,導(dǎo)致查詢性能越來越差。這時(shí),ES 后臺會(huì)有一個(gè)單獨(dú)線程專門合并 segment,將零碎的小的 segment 合并成一個(gè)大的 segment;

6、經(jīng)過一段時(shí)間(默認(rèn)30 min)或者 tanslog 滿了(默認(rèn)512M),會(huì)將文件系統(tǒng)緩存的 segment 落盤;

7、如果主分片所在的節(jié)點(diǎn)請求執(zhí)行成功,它會(huì)將請求同步轉(zhuǎn)發(fā)到副本分片所在節(jié)點(diǎn),做到主副數(shù)據(jù)的一致性,一旦所有的副本分片都報(bào)告成功,主分片節(jié)點(diǎn)將向協(xié)調(diào)節(jié)點(diǎn)報(bào)告成功,協(xié)調(diào)節(jié)點(diǎn)向客戶端報(bào)告成功。因此,數(shù)據(jù)寫入,主副本之間采用的是同步寫入過程。

image.png
image.png
image.png
image.png
Lucene索引
image.png

image.png

image.png

image.png

正向信息

正向

image.png

image.png

image.png

域索引/數(shù)據(jù)文件

詞向量信息tvx/tvd/tvf

image.png

反向信息(新版本用的是FST,不同于此):

詞典

倒排詞頻信息

倒排詞位置信息

segment的數(shù)據(jù)結(jié)構(gòu)
Inverted Index
Stored Fields
Document Values
Cache

  1. Inverted Index
    Inverted Index就是我們常見的倒排索引, 主要包括兩部分:

一個(gè)有序的數(shù)據(jù)字典 Dictionary(包括單詞 Term 和它出現(xiàn)的頻率)。
與單詞 Term 對應(yīng)的 Postings(即存在這個(gè)單詞的文件)
當(dāng)我們搜索的時(shí)候,首先將搜索的內(nèi)容分解,然后在字典里找到對應(yīng) Term,從而查找到與搜索相關(guān)的文件內(nèi)容。

  1. Stored Field
    本質(zhì)上,Stored Fields 是一個(gè)簡單的鍵值對 key-value。默認(rèn)情況下,Stored Fields是為false的,ElasticSearch 會(huì)存儲整個(gè)文件的 JSON source。

哪些情形下需要顯式的指定store屬性呢?大多數(shù)情況并不是必須的。從_source中獲取值是快速而且高效的。如果你的文檔長度很長,存儲 _source或者從_source中獲取field的代價(jià)很大,你可以顯式的將某些field的store屬性設(shè)置為yes。缺點(diǎn)如上邊所說:假設(shè)你存 儲了10個(gè)field,而如果想獲取這10個(gè)field的值,則需要多次的io,如果從Stored Field 中獲取則只需要一次,而且_source是被壓縮過 的。

這個(gè)時(shí)候你可以指定一些字段store為true,這意味著這個(gè)field的數(shù)據(jù)將會(huì)被單獨(dú)存儲(實(shí)際上是存兩份,source和 Stored Field都存了一份)。這時(shí)候,如果你要求返回field1(store:yes),es會(huì)分辨出field1已經(jīng)被存儲了,因此不會(huì)從_source中加載,而是從field1的存儲塊中加載。

  1. Document Values
    Doc_values 本質(zhì)上是一個(gè)序列化的 列式存儲,這個(gè)結(jié)構(gòu)非常適用于聚合(aggregations)、排序(Sorting)、腳本(scripts access to field)等操作。而且,這種存儲方式也非常便于壓縮,特別是數(shù)字類型。這樣可以減少磁盤空間并且提高訪問速度,ElasticSearch 可以將索引下某一個(gè) Document Value 全部讀取到內(nèi)存中進(jìn)行操作.

Doc_values是存在磁盤的

在es中text類型字段默認(rèn)只會(huì)建立倒排索引,其它幾種類型在建立倒排索引的時(shí)候還會(huì)建立正排索引,當(dāng)然es是支持自定義的。在這里這個(gè)正排索引其實(shí)就是Doc Value。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容