最近在參與一個基於Elasticsearch作為底層數據框架提供大數據量(億級)的實時統計查詢的方案設計工作,花了些時間學習Elasticsearch的基礎理論知識,整理了一下,希望能對Elasticsearch感興趣/想了解的同學有所幫助。 同時也希望有發現內容不正確或者有疑問的地方,望指明,一起探討,學習,進步。
介紹
Elasticsearch 是一個分散式可擴展的實時搜索和分析引擎,一個建立在全文搜索引擎 Apache Lucene(TM) 基礎上的搜索引擎.當然 Elasticsearch 並不僅僅是 Lucene 那麼簡單,它不僅包括了全文搜索功能,還可以進行以下工作:
- 分散式實時文件存儲,並將每一個欄位都編入索引,使其可以被搜索。
- 實時分析的分散式搜索引擎。
- 可以擴展到上百台伺服器,處理PB級別的結構化或非結構化數據。
基本概念
先說Elasticsearch的文件存儲,Elasticsearch是面向文檔型資料庫,一條數據在這裡就是一個文檔,用JSON作為文檔序列化的格式,比如下面這條用戶數據:
{
"name" : "John",
"sex" : "Male",
"age" : 25,
"birthDate": "1990/05/01",
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
用Mysql這樣的資料庫存儲就會容易想到建立一張User表,有balabala的欄位等,在Elasticsearch里這就是一個文檔,當然這個文檔會屬於一個User的類型,各種各樣的類型存在於一個索引當中。這裡有一份簡易的將Elasticsearch和關係型數據術語對照表:
關係資料庫 ? 資料庫 ? 表 ? 行 ? 列(Columns)
Elasticsearch ? 索引(Index) ? 類型(type) ? 文檔(Docments) ? 欄位(Fields)
一個 Elasticsearch 集群可以包含多個索引(資料庫),也就是說其中包含了很多類型(表)。這些類型中包含了很多的文檔(行),然後每個文檔中又包含了很多的欄位(列)。Elasticsearch的交互,可以使用Java API,也可以直接使用HTTP的Restful API方式,比如我們打算插入一條記錄,可以簡單發送一個HTTP的請求:
PUT /megacorp/employee/1
{
"name" : "John",
"sex" : "Male",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
更新,查詢也是類似這樣的操作,具體操作手冊可以參見Elasticsearch權威指南
索引
Elasticsearch最關鍵的就是提供強大的索引能力了,其實InfoQ的這篇時間序列資料庫的秘密(2)——索引寫的非常好,我這裡也是圍繞這篇結合自己的理解進一步梳理下,也希望可以幫助大家更好的理解這篇文章。
Elasticsearch索引的精髓:
一切設計都是為了提高搜索的性能
另一層意思:為了提高搜索的性能,難免會犧牲某些其他方面,比如插入/更新,否則其他資料庫不用混了。前面看到往Elasticsearch里插入一條記錄,其實就是直接PUT一個json的對象,這個對象有多個fields,比如上面例子中的name, sex, age, about, interests,那麼在插入這些數據到Elasticsearch的同時,Elasticsearch還默默1的為這些欄位建立索引--倒排索引,因為Elasticsearch最核心功能是搜索。
Elasticsearch是如何做到快速索引的
InfoQ那篇文章里說Elasticsearch使用的倒排索引比關係型資料庫的B-Tree索引快,為什麼呢?
什麼是B-Tree索引?
上大學讀書時老師教過我們,二叉樹查找效率是logN,同時插入新的節點不必移動全部節點,所以用樹型結構存儲索引,能同時兼顧插入和查詢的性能。因此在這個基礎上,再結合磁碟的讀取特性(順序讀/隨機讀),傳統關係型資料庫採用了B-Tree/B+Tree這樣的數據結構: