ES 基礎知識點總結

萌新J發表於2021-07-21

為什麼使用 ES?

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

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

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

 

概念

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

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

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

欄位:相當於 MySQL 的列概念。

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

副本:分片的複製,可以提高吞吐量(查詢請求可以直接走副本)和分割槽容錯性(分片所在的節點當機後包含該分片副本的節點可以代替分片作用)

 

語法結構

query條件

Match:匹配查詢

Balance:用於匹配的欄位(相當於列名),如果是一個字串就是部分匹配,如果是一個數字型別,就是短語查詢。比如address:”a   b  c”那麼只要包含a,b,c三個中任意一個就算匹配(如果abc連在一起那麼就是包含完整的abc)。短語匹配就相當於Match_phrase,完整匹配

 

Match_phrase:短語匹配

無論是數字還是字串都是完整匹配,以 address:"abc" 為例,address 包含 "abc" 這個字串就算匹配。

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

 

Match_all:所有欄位

 

Multi_match:多欄位匹配

多個欄位只要有一個包含就滿足,返回,同時也支援分詞匹配

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

 

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

Must:必須滿足的

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

Must_not:必須不滿足

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

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

 

 

Term:檢索數字型別

作用與match一樣,但是它只能檢索數字型別,字串型別不起作用。一般約定term用來檢索數字,其他用match

這裡的 balance 是數字型別,雙引號不需要加。

 

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視訊

相關文章