ES 基礎知識點總結


為什么使用 ES?

在傳統的數據庫中,如果使用某列記錄某件商品的標題或簡介。在檢索時要想使用關鍵詞來查詢某個記錄,那么是很困難的,假設搜索關鍵詞 "小米",那么 sql 語句就是 

select *  from product where title like concat("%","小米","%")

這樣即使 title 列上包含索引,索引也會失效。而如果使用全文索引,因為 B+ 樹不支持全文索引,所以選擇了全文索引就失去了 B+ 遍歷高效的優點。所以 ES 就登場了,ES 之所以能高效檢索,主要原因就是其倒排索引的特點。常規的索引,也就是正向索引,查詢的過程是獲取整條數據,然后從整條數據中來匹配關鍵詞,如果包含就返回。而倒排索引是將數據拆分成多個關鍵詞,每個關鍵詞都作為一個倒排索引,然后查詢時直接判斷匹配,如果存在就返回該數據。這樣因為使用了索引效率就極大的提高了。

 

概念

索引:相當於 MySQL 的庫概念。

類型:相當於 MySQL 的表概念,在 ES7被移除。

文檔:相當於 MySQL 的行記錄概念。

字段:相當於 MySQL 的列概念。

分片:將某一類字段的文檔拆分出來作為一個分片,查詢時如果是這個字段的,直接去這個分片里查,可以提高系統整體的吞吐量。

副本:分片的復制,可以提高吞吐量(查詢請求可以直接走副本)和分區容錯性(分片所在的節點宕機后包含該分片副本的節點可以代替分片作用)

 

語法結構

query條件

Match:匹配查詢

Balance:用於匹配的字段(相當於列名),會對條件值進行分詞,再去 查詢,條件之間是 or 關系

字段后面加一個“.keyword”表示查詢完全匹配的字段。以address:”abc”為例,address必須為abc才算匹配。

 

Match_phrase:短語匹配

和 match 一樣也是先分詞再查詢,只不過條件是 and 關系 

{
  "query": {
    "match_phrase": {
        "content" : {
            "query" : "我的寶馬多少馬力",
            "slop" : 1     #允許少匹配的分詞個數
        }
    }
  }
}    

 

Match_all:所有字段匹配,其相反的是 match_none

 

Multi_match:多字段匹配

match 匹配的多字段匹配,多個字段只要有一個包含就滿足,返回,同時也支持分詞匹配

Address、city列只要有一個包含 mill和movico其中一個就滿足

 

Bool:復合查詢(多條件復雜查詢)

Must:必須滿足的

  Match:匹配查詢,字符串模糊查詢,數字精確查詢

Must_not:必須不滿足

Should:可以滿足可以不滿足,滿足的得分更高,排在前面。

Filter:與must一樣,但是不會貢獻得分

 

 

Term:精確匹配

精確匹配,查詢完全匹配的字段值所對應的文檔

 

Terms:類似於 term,匹配多個值

如果字段是給定幾個值中的一個就返回 

 

其他

分頁,指定返回的字段 

 

結果分析

 

聚合

聚合就是在查詢結果的基礎上,進行分組統計,聚合可以迭代。

AVG:平均值聚合

Terms:類型聚合

...等等

Aggs:表示是聚合,與query一樣

  ageAgg:聚合名,

    Terms:類型聚合

      Field:字段名

      Size:取多少種

 

結果分析

Key:年齡

Doc_count:結果數

ageAvg:子聚合

  Value:子聚合的值

 

Mapping 映射

映射主要指的是 ES 字段的單位。主要包括 Integer、long、keyword、text、nested(嵌入式,防止扁平化處理)。

查看某個索引下的映射

Get  /bank/_mapping 

 

添加索引並指定其字段映射

 

為某個索引添加新的字段並指定映射

 

修改字段映射

不支持對已存在的索引進行映射修改。可以使用數據遷移來完成。

1、創建臨時索引

2、將之前的索引數據遷移到創建的臨時索引中。

Source:原來的索引, index 來指定索引名也可以在index后面指定type,但是因為7開始移除了類型(相當於數據庫表),所以不需要指定了。

Dest:要轉移的索引名, index 來指定索引名。以當前例子來看就是 newbank

3、將原索引刪除,再創建新的索引,指定映射。

DELETE bank

4、最后將臨時索引數據遷移到新創建的索引中。

 

扁平化

由於扁平化的占用,在檢索 first 為 John,last 為 white 的文檔時,也會檢索到。所以對於子類中包含兩個或以上屬性的,應該將父類字段映射設為 nested 類型來防止 ES 的扁平化處理。(默認空間的不會進行扁平化,也就是properties下第一層的不會)

例子如下:

映射:

查詢:

聚合:

 

映射結果分析

 

分詞

分詞是 ES 的倒排索引,所以分詞器就決定了 ES 的倒排索引是什么,默認的分詞器是選擇空格隔開的英文作為一個分詞,中文的話每一個字都會是一個分詞。測試分詞效果:

 

如果想使用常用的中文分詞,可以使用 ik 分詞器,可以滿足絕大多數的中文分詞,而對於一些特殊的分詞,可以使用配置自定義的分詞,然后將保存自定義分詞的文件配置到 ik 分詞器中。

 

 

原理

ES架構

ES 是一個開源的高拓展分布式全文搜索引擎,這句話表現出 ES 的兩個重要特點,全文搜索和高拓展分布式。其中全文搜索可以通過倒排索引體現出,而高拓展的分布式則可以通過其架構體現出。上面就是一個 ES 集群的架構圖,Node1、Node2、Node3 是三個節點服務器,其中 Node1 是主節點。在 ES 中配置了三個分片(P0、P1、P2,這三個分片保存着 ES 整個數據),同時,為了保證 ES 的分區容錯性以及查詢效率,每個分片還配置了一個副本(分別是 R0、R1、R2),原分片處理讀和寫操作,副本處理讀操作。在分布中將副本與原分片拆開放置,避免某個節點宕機該分片的數據無法使用。並且在增加節點后,集群會自動分配分片和副本,保證均勻分布在不同的節點上。比如:

單節點:

 二節點:

三節點:

 

操作過程

存儲:根據存儲數據的 hash 取余計算分配的節點位置,選擇分片進行保存,隨后再將保存數據更新到所有副本中。默認情況下當大多數副本都同步完成時,就返回存儲完成的通知。這個可以通過 consistency 參數配置,all 表示必須所有的 副本都同步完成才返回存儲完成的通知,one 表示只要主分片同步完成就返回存儲完成的通知(檢索結果可能會被還未同步的副本處理,造成未檢索到),默認值是 quornum。

 

查詢:輪詢數據所在的分片和副本,發送請求。

 

更新:和存儲一樣,取余得到節點位置,找到分片后更新,再同步到其他副本,等到所有副本都同步完成后再返回更新成功的提示。

 

倒排索引的結構:倒排索引是無法修改的,好處是不用擔心讀寫不一致的問題,但是缺點也非常明顯,會大量的占用空間。為了減少空間占用,引入了段的概念,每個倒排索引都擁有一個段,在每次更新時都會將補充索引寫入段中,然后檢索時就會結合段中的數據和補充索引返回數據。

 

刪除:每個段中都有一個 .del 文件,當該倒排索引被下達刪除請求后,就會在 .del 文件進行標記,隨后檢索就會跳過當前段,也就是邏輯刪除。當倒排索引特別多時,會進行合並,此時會將那些邏輯刪除的段徹底刪除。

 

持久化:ES 數據的保存和檢索都在內存中,這也是它檢索速度快的原因之一,而其也會定期持久化到磁盤。

在分片執行更新、保存數據時,底層還伴隨着定期持久化,在寫入時,會先更新內存,隨后寫入內存中的 translog 里(避免斷電導致內存數據丟失,類似於 mysql 中的 redo log)。然后進行 refresh(默認1s執行一次)到文件系統緩存,更新到系統緩存后數據才能被檢索到。並且后台還會定期 flush(默認30min執行一次) ,將數據持久化到磁盤上。

 

 

 

本文主要參考某谷的ES視頻


免責聲明!

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



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