1. 程式人生 > 其它 >ES(ElasticSearch) 如何建立索引

ES(ElasticSearch) 如何建立索引

ES簡介

在討論 ElasticSearch 之前,不得不提 Apache Lucene,因為 ElasticSearch 的廣泛應用離不開 Lucene 的支援。

Lucene 是一個開源的全文檢索引擎類庫,支援各種分詞以及搜尋相關的實現,可以極大地簡化搜尋開發的成本,但 Lucene 只是一個工具包,在實際專案中進行二次開發,你需要非常熟悉 Lucene 的實現機制以及 API 應用,這樣才能應用 Lucene 的各種特性。

現在有了 ElasticSearch,就可以直接使用基於 Lucene 的各種檢索功能,ElasticSearch 是一個基於 Lucene 的分散式全文檢索框架,在 Lucene 類庫的基礎上實現,可以避免直接基於 Lucene 開發,這一點和 Java 中 Netty 對 IO/NIO 的封裝有些類似。

ElasticSearch 開放了一系列的 RESTful API,基於這些 API,可以快捷地實現各種搜尋功能。另外一方面,除了搜尋相關的功能,ElasticSearch 還對分散式場景下的應用有特別好的支援,包括良好的擴充套件性,可以擴充套件到上百臺伺服器的叢集規模,以及近似實時分析的索引實現。這些特點,使得 ElasticSearch 在各類搜尋場景、大資料分析等業務中廣泛應用。

ES 應用

ElasticSearch 對搜尋的支援非常好,但是和 NoSQL 資料庫一樣,對事務、一致性等的支援較低。

下面是一個實際開發中,常見的資料庫-索引-快取系統架構圖:

可以看到,ElasticSearch 一般是作為永續性資料庫的輔助儲存,是和 SQL & NoSQL 資料庫一起使用,對外提供索引查詢功能。關係型資料庫保證資料更新的準確性,在關係型資料庫更新以後,通過 binlog 同步結合訊息佇列分發的方式,來更新檔案索引,提供一致性保證。

ELK stack

ElasticSearch 是由 Elastic 公司建立的,除了 ElasticSearch,Elastic 公司還有另外兩款產品,分別是 Logstash 及 Kibana 開源專案,這三個開源專案組合在一起稱為 ELK stack。

在 ELK 技術棧中,ElasticSearch 用於資料分析和檢索,Logstash 用於日誌收集,Kibana 用於介面的展示,ELK 可以用於快速查詢資料並可視化分析,在日誌處理、大資料等領域有非常廣泛的應用。ELK 的文件和各種問題手冊非常全面,可以說是開箱即用。

索引如何建立

ElasticSearch 儲存的單元是索引,這一點區別於很多關係型資料庫和 NoSQL 資料庫,比如關係型資料庫是按照關係表的形式組織資料,大部分 NoSQL 資料庫是 K-Value 的鍵值對方式。

ElasticSearch 儲存的基本單元是索引,那麼索引是如何建立的呢?

ElasticSearch 索引的實現基於 Lucene,使用倒排索引的結構,倒排索引的引入,使得 ElasticSearch 可以非常高效地實現各種檔案索引。倒排索引不光是在 ElasticSearch 等元件中應用,它還是百度等搜尋引擎實現的底層技術之一。在搜尋引擎中,索引的建立需要經過網頁爬取、資訊採集、分詞、索引建立的過程,不過在 ElasticSearch 內部儲存的實現中,資料的寫入可以對比搜尋引擎對網頁的抓取和資訊採集的過程,只需要關注分詞和索引的建立。

分詞和索引

分詞是在索引建立中特別重要的一個環節,分詞的策略會直接影響索引結果。Lucene 提供了多種分詞器,分詞器是一個可插拔的元件,包括內建的標準分詞器, 也可以引入對中文支援較好的 IKAnalyze 中文分詞器等。

下面我們通過一個例子來了解分詞的具體過程,假設我們在 ElasticSearch 中新增了兩個文件,每個文件包含如下內容:

文件1,Joker and Tim are good friends.

文件2,Good friends should help each other.

英文是有單詞的,單詞之間通過空格進行拆分,所以對英文的分詞相對容易,比如上面的內容,可以直接對字串按照空格拆分,得到分詞後的陣列。

Joker/and/Tim/are/good/friends
Good/friends/should/help/each/other

如果是中文,除了標點符號以外,一個整句是沒有分隔符的,處理起來就會複雜得多。一般來說,中文分詞用得比較多的策略是基於字典的最長字串匹配方式,這種策略可以覆蓋大多數場景,不過還是有一小部分天然存在歧義的文件是無法處理的。比如「學生會組織各種活動」,按照最長串匹配的方式,可以切分成“學生會/組織各種活動”,但實際要表達的可能是“學生/會/組織各種活動”。

現在有一個很火熱的學科叫作自然語言處理(NLP),研究的問題就包括如何消除語義分析中的各種歧義問題,感興趣的話可以去了解下。

建立索引

索引儲存的結構是倒排索引,什麼是倒排索引呢?倒排索引是相對於正排索引來說的,倒排索引描述了一個對映關係,包括文件中分詞後的結果,以及分別包含這些單詞的文件列表。

索引描述的其實就是關鍵詞和文件的關係,正排索引就是“文件—關鍵詞”的格式,倒排索引則相反,是“關鍵詞—文件”的格式。可以看到,當需要使用關鍵詞進行檢索時,使用倒排索引才能實現快速檢索的目的。

針對上面的分詞示例,我們簡單起見,統一為小寫,把分詞之後的單片語成一個不重複的分詞列表,為了更好地進行查詢,可以按照字典序排序。

and,are,each,friends,good,help,jerry,other,should,tom

比如,其中“friends”在文件 1 和文件 2 中都出現了,“Joker”和“Tim”只在文件 1 中出現了 1 次,其他的單詞也進行同樣地處理,於是我們可以構建下面的倒排索引:

分詞 文件
friends 文件1,文件2
Joker 文件1
Tim 文件1
good 文件1,文件2
其他同理 。。。

具體到資料結構的實現,可以通過實現一個字典樹,也就是 Trie 樹,對字典樹進行擴充套件,額外儲存對應的資料塊地址,定位到具體的資料位置。

對比B+樹

MySQL InnoDB 引擎的索引實現是基於 B+ 樹,那麼同樣是索引,倒排索引和 B+ 樹索引有哪些區別呢?

嚴格地說,這兩類索引是不能在一起比較的,B+ 樹描述的是索引的資料結構,而倒排索引是通過索引的組織形式來命名的。比如我們上面的例子中,倒排指的是關鍵詞和文件列表的結構關係。

對於資料庫來說,索引的作用是提高資料查詢的效能,考慮到磁碟定址的特性,選擇了 B+ 樹作為索引的實現結構,可以更好地實現通過主鍵以及通過區間範圍查詢的要求。

對於倒排索引,則是對應具體的應用場景,我們在搜尋中是通過一些關鍵詞,定位到具體的文件。所以倒排索引實現的是根據關鍵詞,也就是分詞的結果,去查詢文件,或者不同的網頁。