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 數據庫一樣,對事務、一致性等的支持較低。

下面是一個實際開發中,常見的數據庫-索引-緩存系統架構圖:
image.png

可以看到,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+ 樹作為索引的實現結構,可以更好地實現通過主鍵以及通過區間范圍查找的要求。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM