Elasticsearch-6.x 倒排索引,doc_values,Fielddata, store研究

一.倒排索引
倒排索引的概念,感興趣的能夠點擊查看<<ES權威指南中關於倒排索引的解釋>>
算法

也能夠查看elasticsearch簡介和倒排序索引介紹這篇文章,寫的很清晰。數據庫

1.1 字段和倒排索引的關係
首先,在es中,咱們能夠把一個doc(文檔)理解爲數據庫中的一行數據,每一個doc對應多個field(字段),例如:
app

PUT /employee/group/1
{
    "age" : 25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}
PUT /employee/group/2
{
    "age" :         32,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}
es中,會在_source中將數據存一份,而後,寫入數據的同時,自動生成mapping信息,根據mapping信息,生成字段對應的倒排索引文件。











elasticsearch

自動生成的mapping以下:this

{
  "employee": {
    "mappings": {
      "group": {
        "properties": {
          "about": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "age": {
            "type": "long"
          },
          "interests": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}
按照字段,分別生成倒排索引文件,而後檢索字段的時候,搜索字段對應的倒排索引文件便可,以下:






























.net

age字段:rest

age字段由於是long類型,整個字段無需分詞(term,token),直接按字段值作倒排索引。blog

age-1-倒排索引文件
term詞條    docID
25    1
32    2
about字段自己爲text類型,支持分詞,about.keyword多域字段爲keyword類型,按整詞做爲term詞條,因此產生about,about.keyword兩個字段的倒排索引文件。



排序

about-1 倒排索引文件
term詞條    docID
i    1,2
love    1
to    1,2
go    1
rock    1,2
climbing    1
like    2
collect     2
albums    2
about.keyword-1倒排索引文件
term詞條    docID
I love to go rock climbing    1
I like to collect rock albums    2
ES檢索過程:














索引

1.根據檢索字段,若是是text類型的,按照寫入索引時的分詞機制,進行查詢關鍵字分詞,

2.查詢字段對應的倒排索引文件,查詢term分詞,獲得對應的docID

3.根據docID,得到doc,顯示查詢結果。

 

提問:
1.about.keyword的做用,換而言之,keyword數據類型和text數據類型的區別?
"about":"I love to go rock climbing"
對上面的about字段,keyword數據類型只支持精確搜索,由於keyword創建的索引文件的term,是全詞創建索引,沒有分詞,因此,對於檢索 about:"i",若是格式爲keyword將返回null,無搜索結果。若是格式爲text,則分詞後創建索引,搜索  about:"i",有結果,由於有I 的term,因而可知,分詞機制對搜索影響很大,由於term只能徹底匹配,纔會獲得term對應的文檔。


 

倒排索引的不足
1.倒排索引,按分詞創建,創建後不可修改。

ES針對修改倒排索引,使用的是再合併策略:對修改的數據創建新的,小的索引文件,記錄時間,新的索引文件和舊的索引文件合併,修改的部分,按時間最新覆蓋。

2.倒排索引能夠很快的經過分詞,獲得包含分詞的文檔。可是,若是咱們已知文檔,想獲得文檔擁有哪些分詞,須要遍歷整個倒排索引文件,影響效率。

解決辦法是引入doc_values,doc_values是文檔對應的分詞造成的索引文件。

3.倒排索引十分依賴分詞機制,分詞機制很差,則搜索結果不理想

ES提供不少分詞機制,也支持自定義分詞機制。固然,若是不須要分詞,只須要精準匹配,直接創建keyword類型數據便可。

 

二.doc_values 文檔值
2.1. doc_values是什麼
doc_values是elasticsearch中,對於倒排索引的部分缺點進行部分補充的功能。查看dov_values官方解釋

倒排索引很方便單項查看 分詞對應的文檔,可是不利於反向查看,文檔全部的分詞。doc_values能夠理解爲反向的倒排索引,

doc_values存放的是文檔對應的分詞

2.1 doc_values的應用場景
上面說doc_values 是爲了知足反向查詢倒排索引而創建的。那麼,什麼樣的狀況咱們須要用到doc_values呢。大體說來,聚合,排序,都會用到doc_values,

首先,咱們進行一次聚合。

//增長一條記錄
PUT /employee/group/3
{
    "age" :         32,
    "about" :       "I like to read book",
    "interests":  [ "music","books" ]
}
//查詢abount中有i的,按age聚合,統計文檔數
GET /employee/_search
{
  "query" : {
    "match" : {
      "about" : "i"
    }
  },
  "aggs" : {
    "res": {
      "terms" : {
        "field" : "age"
      }
    }
  }
}
這條語句主要是爲了分析,每一個數據出現的次數,例如,music有多少人喜歡,sports有多少人喜歡。結果以下:






















{
  "aggregations": {
    "res": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": 32,                   //age=32的有兩個文檔
          "doc_count": 2
        },
        {
          "key": 25,                   //age=25的有一個文檔
          "doc_count": 1
        }
      ]
    }
  }
}
將上面的查詢聚合過程分解:

















1.執行query,查詢about中包含i這個term的doc。獲得文檔1,2,3

2.獲得文檔1,2,3後,咱們分析1,2,3的age字段,判斷每一個age的有多少人。

在第2步中,若是咱們只有倒排索引文件,咱們須要遍歷整個倒排索引,去獲取,1,2,3文檔的age索引文件,按照age索引文件的term(age是數值類型,整詞造成倒排索引,不進行分詞),即age的值,而後合併統計文檔數。

可是若是咱們有doc_values以後,就很方便統計了。

doc_values是和倒排索引同時創建的。一樣按索引/類型/字段區分索引文件,doc_value生成數據爲:

age-1-doc_values索引文件
文檔ID    包含的term(不分詞的term,即字段對應的值)
1    25
2    32
3    32
 




有了doc_values的查詢聚合過程以下:

1.執行query,查詢about中包含i這個term的doc。獲得文檔1,2,3

2.獲得文檔1,2,3後,查詢age對應的doc_values索引文件,將age合併,計數,獲得25->1,32->2,返回結果。

搜索和聚合是相互緊密纏繞的。搜索使用倒排索引查找文檔,聚合操做收集和聚合 doc values 裏的數據。

注意:
doc_values對不分詞的字段默認開啓,包括about.keyword這類多域字段,對分詞字段默認關閉,即about字段

#分詞字段# 從數據類型來看,text默認進行分詞,keyword,long,int,double,複雜數據類型等默認不進行分詞

剛纔的描述中,常常強調doc_values存放的是 文檔對應的分詞數,這句話是容易引發歧義的,可是又是正確的,若是,該字段不容許分詞,則該字段的值,就是該文檔在這個索引文件的惟一分詞(即term),對於能分詞的字段,doc_values是默認關閉,可是能夠手動開啓,這個時候,doc_values存放的是文檔對應的分詞數 ,這句話就是正確的。

因此,對於doc_values的用途,ES官網的說法是:

Doc values 不只能夠用於聚合。 任何須要查找某個文檔包含的值的操做都必須使用它。 除了聚合,還包括排序,訪問字段值的腳本,父子關係處理,參見 父-子關係文檔 

#爲何對分詞字段關閉#  沒找到官方解釋 、我的見解:對分詞字段,開啓doc_values,產生的索引文件佔用磁盤過大,處理的時候,消耗cpu資源,

 

doc_values的優缺點
1.doc_values 提升了聚合,排序,全部針對字段值的操做的效率,

2.doc_values加大了磁盤空間,可是ES提供了doc_values的壓縮算法,對doc_values進行了大量壓縮。並且,用不到能夠禁用,節省空間。
 

三.Fielddata 
3.1 fielddata是什麼
由於doc_values不針對分詞字段,那麼,若是必定要對分詞字段的term分詞進行聚合,該怎麼辦呢?

在es中,對分詞的field,直接執行聚合操做,會報錯,

{
        "type": "illegal_argument_exception",
        "reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [about] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."
      }
大概意思是說,你必需要打開fielddata,而後將正排索引數據加載到內存中,才能夠對分詞的field執行聚合操做,並且會消耗很大的內存



fielddata就是知足該需求的,可是,由於過於消耗資源,因此默認關閉。

fielddata結構和doc_values相同,區別是.fielddata運算時在內存中生成,純內存計算,doc_values放在磁盤中便可

有需求時,在mapping中打開fielddata開關。默認false關閉。

doc_values和fielddata詳細說明能夠查看博客 elasticsearch的Doc Values 和 Fielddata

四.store存儲
字段獨立於_source,單獨存儲,

注:_source中依然會存儲該字段

優勢: ES中,全部數據統一存在_source中,若是隻是查詢一個小字段,卻要把_source中的整條數據顯示後,再從_source中取出對應的字段,浪費資源。

缺點: 加大磁盤使用。

應用場景: 若是_source很大,頻繁使用的字段很小,則應該store該字段,這樣不須要每次都將_source加載完後,在查找該字段。 ———————————————— 版權聲明:本文爲CSDN博主「靈520翼」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/u013501457/article/details/86009050

相關文章
相關標籤/搜索