一切設計都是爲了提升搜索的性能數據庫
倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引。通俗地來說,正向索引是經過key找value,反向索引則是經過value找key。json
先來回憶一下咱們是怎麼插入一條索引記錄的:數組
若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。app
curl -X PUT "localhost:9200/user/_doc/1" -H 'Content-Type: application/json' -d' { "name" : "Jack", "gender" : 1, "age" : 20 } '
其實就是直接PUT一個JSON的對象,這個對象有多個字段,在插入這些數據到索引的同時,Elasticsearch還爲這些字段創建索引——倒排索引,由於Elasticsearch最核心功能是搜索。curl
那麼,倒排索引是個什麼樣子呢?分佈式
首先,來搞清楚幾個概念,爲此,舉個例子:微服務
假設有個user索引,它有四個字段:分別是name,gender,age,address。畫出來的話,大概是下面這個樣子,跟關係型數據庫同樣源碼分析
Term(單詞):一段文本通過分析器分析之後就會輸出一串單詞,這一個一個的就叫作Term(直譯爲:單詞)性能
Term Dictionary(單詞字典):顧名思義,它裏面維護的是Term,能夠理解爲Term的集合學習
Term Index(單詞索引):爲了更快的找到某個單詞,咱們爲單詞創建索引
Posting List(倒排列表):倒排列表記錄了出現過某個單詞的全部文檔的文檔列表及單詞在該文檔中出現的位置信息,每條記錄稱爲一個倒排項(Posting)。根據倒排列表,便可獲知哪些文檔包含某個單詞。(PS:實際的倒排列表中並不僅是存了文檔ID這麼簡單,還有一些其它的信息,好比:詞頻(Term出現的次數)、偏移量(offset)等,能夠想象成是Python中的元組,或者Java中的對象)
(PS:若是類比現代漢語詞典的話,那麼Term就至關於詞語,Term Dictionary至關於漢語詞典自己,Term Index至關於詞典的目錄索引)
咱們知道,每一個文檔都有一個ID,若是插入的時候沒有指定的話,Elasticsearch會自動生成一個,所以ID字段就很少說了
上面的例子,Elasticsearch創建的索引大體以下:
name字段:
age字段:
gender字段:
address字段:
若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。
Elasticsearch分別爲每一個字段都創建了一個倒排索引。好比,在上面「張三」、「北京市」、22 這些都是Term,而[1,3]就是Posting List。Posting list就是一個數組,存儲了全部符合某個Term的文檔ID。
只要知道文檔ID,就能快速找到文檔。但是,要怎樣經過咱們給定的關鍵詞快速找到這個Term呢?
固然是建索引了,爲Terms創建索引,最好的就是B-Tree索引(PS:MySQL就是B樹索引最好的例子)。
首先,讓咱們來回憶一下MyISAM存儲引擎中的索引是什麼樣的:
咱們查找Term的過程跟在MyISAM中記錄ID的過程大體是同樣的
MyISAM中,索引和數據是分開,經過索引能夠找到記錄的地址,進而能夠找到這條記錄
在倒排索引中,經過Term索引能夠找到Term在Term Dictionary中的位置,進而找到Posting List,有了倒排列表就能夠根據ID找到文檔了
(PS:能夠這樣理解,類比MyISAM的話,Term Index至關於索引文件,Term Dictionary至關於數據文件)
(PS:其實,前面咱們分了三步,咱們能夠把Term Index和Term Dictionary當作一步,就是找Term。所以,能夠這樣理解倒排索引:經過單詞找到對應的倒排列表,根據倒排列表中的倒排項進而能夠找到文檔記錄)
爲了更進一步理解,下面從網上摘了兩張圖來具現化這一過程:
若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。