一、ES的數(shù)據(jù)存儲結(jié)構(gòu):
ES底層使用 Lucene 存儲數(shù)據(jù),Lucene 的索引包含以下部分:
A Lucene index is made of several components: an inverted index, a bkd tree, a column store (doc values), a document store (stored fields) and term vectors, and these components can communicate thanks to these doc ids.
其中:
inverted index:倒排索引。
bkd tree: Block k-d tree,用于在高維空間內(nèi)做索引,如地理坐標(biāo)的索引。
column store:doc values,列式存儲,批量讀取連續(xù)的數(shù)據(jù)以提高排序和聚合的效率。
document store:Store Fileds,行式存儲文檔,用于控制 doc 原始數(shù)據(jù)的存儲,其中占比最大的是 source 字段。
term vectors:用于存儲各個詞在文檔中出現(xiàn)的位置等信息。
二、ES常見配置項說明:
在很多場合下,我們并不需要存儲上述全部信息,因此可以通過設(shè)置 mappings 里面的屬性來控制哪些字段是我們需要存儲的、哪些是不需要存儲的。而 ES 的 mapping 中有很多設(shè)置選項,這些選項如果設(shè)置不當(dāng),有的可能浪費存儲空間,有的可能導(dǎo)致無法使用 Aggregation,有的可能導(dǎo)致不能檢索。下面就簡單介紹下 ES 中常見的存儲與檢索的 mapping 配置項:
配置項 | 作用 | 注意事項 | 默認(rèn)值 |
---|---|---|---|
_all | 提供跨字段全文檢索 | (1)會占用額外空間,把 mapping 中的所有字段通過空格拼接起來做索引,在跨字段全文檢索才需要打開; (2)在 v6.0+已被棄用,v7.0會正式移除,可以使用 [copy_to] 來自定義組合字段 | 關(guān)閉 |
_source | 存儲 post 提交到ES的原始 json 內(nèi)容 | (1)會占用很多存儲空間。數(shù)據(jù)壓縮存儲,讀取會有額外解壓開銷。(2)不需要讀取原始字段內(nèi)容可以考慮關(guān)閉,但關(guān)閉后無法 reindex | 開啟 |
store | 是否單獨存儲該字段 | (1)會占用額外存儲空間,與 source 獨立,同時開啟 store 和 source 則會將該字段原始內(nèi)容保存兩份,不同字段單獨存儲,不同字段的數(shù)據(jù)在磁盤上不連續(xù),若讀取多個字段則需要查詢多次,如需讀取多個字段,需權(quán)衡比較 source 與 store 效率 | 關(guān)閉 |
doc_values | 支持排序、聚合 | 會占用額外存儲空間,與 source 獨立,同時開啟 doc_values 和 _source 則會將該字段原始內(nèi)容保存兩份。doc_values 數(shù)據(jù)在磁盤上采用列式存儲,關(guān)閉后無法使用排序和聚合 | 開啟 |
index | 是否加入倒排索引 | 關(guān)閉后無法對其進行搜索,但字段仍會存儲到 _source 和 doc_values,字段可以被排序和聚合 | 開啟 |
enabled | 是否對該字段進行處理 | 關(guān)閉后,只在 _source中存儲,類似 index 與 doc_values 的總開關(guān) | 開啟 |
在ES的 mapping 設(shè)置里,all,source 是 mapping 的元數(shù)據(jù)字段(Meta-Fields),store、doc_values、enabled、index 是 mapping 參數(shù)。
1、_all:
all 字段的作用是提供跨字段查詢的支持,把 mapping 中的所有字段通過空格拼接起來做索引。ES在查詢的過程中,需要指定在哪一個field里面查詢。
{
“name”: “smith”,
“email”: "John@example.com"
}
用戶在查詢時,想查詢叫做 John 的人,但不知道 John 出現(xiàn)在 name 字段中還是在 email 字段中,由于ES是為每一個字段單獨建立索引,所以用戶需要以 John 為關(guān)鍵詞發(fā)起兩次查詢,分別查詢name字段和email字段。
如果開啟了 all 字段,則ES會在索引過程中創(chuàng)建一個虛擬的字段 all,其值為文檔中各個字段拼接起來所組成的一個很長的字符串(例如上面的例子,all 字段的內(nèi)容為字符串 “smith John@example.com”)。隨后,該字段將被分詞打散,與其他字段一樣被收入倒排索引中。由于 all 字段包含了所有字段的信息,因此可以實現(xiàn)跨字段的查詢,用戶不用關(guān)心要查詢的關(guān)鍵詞在哪個字段中。
由于該字段的內(nèi)容都來自 source 字段,因此默認(rèn)情況下,該字段的內(nèi)容并不會被保存,可以通過設(shè)置 store 屬性來強制保存 all 字段。開啟 all 字段,會帶來額外的CPU開銷和存儲,如果沒有使用到,可以關(guān)閉 all 字段。
2、_source:
source 字段用于存儲 post 到 ES 的原始 json 文檔。為什么要存儲原始文檔呢?因為 ES 采用倒排索引對文本進行搜索,而倒排索引無法存儲原始輸入文本。一段文本交給ES后,首先會被分析器(analyzer)打散成單詞,為了保證搜索的準(zhǔn)確性,在打散的過程中,會去除文本中的標(biāo)點符號,統(tǒng)一文本的大小寫,甚至對于英文等主流語言,會把發(fā)生形式變化的單詞恢復(fù)成原型或詞根,然后再根據(jù)統(tǒng)一規(guī)整之后的單詞建立倒排索引,經(jīng)過如此一番處理,原文已經(jīng)面目全非。因此需要有一個地方來存儲原始的信息,以便在搜到這個文檔時能夠把原文返回給查詢者。
那么一定要存儲原始文檔嗎?不一定!如果沒有取出整個原始 json 結(jié)構(gòu)體的需求,可以在 mapping 中關(guān)閉 source 字段或者只在 source 中存儲部分字段(使用store)。 但是這樣做有些負(fù)面影響:
(1)不能獲取到原文
(2)無法reindex:如果存儲了 source,當(dāng) index 發(fā)生損壞,或需要改變 mapping 結(jié)構(gòu)時,由于存在原始數(shù)據(jù),ES可以通過原始數(shù)據(jù)自動重建index,如果不存 source 則無法實現(xiàn)
(3)無法在查詢中使用script:因為 script 需要訪問 source 中的字段
3、store:
store 決定一個字段是否要被單獨存儲。大家可能會有疑問,source 里面不是已經(jīng)存儲了原始的文檔嘛,為什么還需要一個額外的 store 屬性呢?原因如下:
(1)如果禁用了 source 保存,可以通過指定 store 屬性來單獨保存某個或某幾個字段,而不是將整個輸入文檔保存到 source 中。
(2)如果 source 中有長度很長的文本(如一篇文章)和較短的文本(如文章標(biāo)題),當(dāng)只需要取出標(biāo)題時,如果使用 source 字段,ES需要讀取整個 source 字段,然后返回其中的 title,由此會引來額外的IO開銷,降低效率。此時可以選擇將 title 的 store 設(shè)置為true,在 source 字段外單獨存儲一份。讀取時不必在讀取整 source 字段了。但是需要注意,應(yīng)該避免使用 store 查詢多個字段,因為 store 的存儲在磁盤上不連續(xù),ES在讀取不同的 store 字段時,每個字段的讀取均需要在磁盤上進行查詢操作,而使用 source 字段可以一次性連續(xù)讀取多個字段。
4、doc_values:
倒排索引可以提供全文檢索能力,但是無法提供對排序和數(shù)據(jù)聚合的支持。doc_values 本質(zhì)上是一個序列化的列式存儲結(jié)構(gòu),適用于聚合(aggregations)、排序(Sorting)、腳本(scripts access to field)等操作。默認(rèn)情況下,ES幾乎會為所有類型的字段存儲doc_value,但是 text 或 text_annotated 等可分詞字段不支持 doc values 。如果不需要對某個字段進行排序或者聚合,則可以關(guān)閉該字段的doc_value存儲。
5、index:
控制倒排索引,用于標(biāo)識指定字段是否需要被索引。默認(rèn)情況下是開啟的,如果關(guān)閉了 index,則該字段的內(nèi)容不會被 analyze 分詞,也不會存入倒排索引,即意味著該字段無法被搜索。
6、enabled:
這是一個 index 和 doc_value 的總開關(guān),如果 enabled 設(shè)置為false,則這個字段將會僅存在于 source 中,其對應(yīng)的 index 和 doc_value 都不會被創(chuàng)建。這意味著,該字段將不可以被搜索、排序或者聚合,但可以通過 source 獲取其原始值。
7、term_vector:
在對文本進行 analyze 的過程中,可以保留有關(guān)分詞結(jié)果的相關(guān)信息,包括單詞列表、單詞之間的先后順序、單詞在原文中的位置等信息。查詢結(jié)果返回的高亮信息就可以利用其中的數(shù)據(jù)來返回。默認(rèn)情況下,term_vector是關(guān)閉的,如有需要(如加速highlight結(jié)果)可以開啟該字段的存儲。
三、doc_values 詳細(xì)說明:
1、doc_values 的作用:
基于 lucene 的 solr 和 es 都是使用倒排索引實現(xiàn)快速檢索的,也就是通過建立 “搜索關(guān)鍵詞 ==>文檔ID列表” 的關(guān)系映射實現(xiàn)快速檢索,但是倒排索引也是有缺陷的,比如我們需要字段值做一些排序、分組、聚合操作,lucene 內(nèi)部會遍歷提取所有出現(xiàn)在文檔集合的排序字段,然后再次構(gòu)建一個最終的排好序的文檔集合list,這個步驟的過程全部維持在內(nèi)存中操作,而且如果排序數(shù)據(jù)量巨大的話,非常容易就造成solr內(nèi)存溢出和性能緩慢。
doc values 就是在構(gòu)建倒排索引時,會對開啟 doc values 的字段額外構(gòu)建一個有序的 "document文檔 ==> field value“ 的列式存儲映射,從而實現(xiàn)對指定字段進行排序和聚合時對內(nèi)存的依賴,提升該過程的性能。默認(rèn)情況下每個字段的 doc values 都是開啟的,當(dāng)然 doc values 也會耗費一定的磁盤空間。
另外 doc values 保存在操作系統(tǒng)的磁盤中,當(dāng) doc values 大于節(jié)點的可用內(nèi)存,ES 可以從操作系統(tǒng)頁緩存中加載或彈出,從而避免發(fā)生 JVM 內(nèi)存溢出的異常,docValues 遠(yuǎn)小于節(jié)點的可用內(nèi)存,操作系統(tǒng)自然將所有Doc Values存于內(nèi)存中(堆外內(nèi)存),有助于快速訪問。
2、doc_values 與 source 的區(qū)別?使用 docvalue_fields 檢索指定的字段?
post 提交到 ES 的原始 Json 文檔都存儲在 source 字段中,默認(rèn)情況下,每次搜索的命中結(jié)果都包含文檔 source,即使僅請求少量字段,也必須加載并解析整個 source 對象,而 source 每次使用時都必須加載和解析,所以使用 source 非常慢。為避免該問題,當(dāng)我們只需要返回相當(dāng)少的支持 doc_values 的字段時,可以使用 docvalue_fields 參數(shù)獲取選定字段的值。
doc values 存儲與 _source 相同的值,但在磁盤上基于列的結(jié)構(gòu)中進行了優(yōu)化,以進行排序和匯總。由于每個字段都是單獨存儲的,因此 Elasticsearch 僅讀取請求的字段值,并且可以避免加載整個文檔 _source。通過 docvalue_fields 可以從建好的列式存儲結(jié)果中直接返回字段值,畢竟 source 是從一大片物理磁盤去,理論上從 doc values 處拿這個字段值會比 source 要快一點,頁面抖動少一點。
3、如何在 ES 中使用 doc values?
doc values 通過犧牲一定的磁盤空間帶來的好處主要有兩個:
節(jié)省內(nèi)存
提升排序,分組等聚合操作的性能
那么我們?nèi)绾问褂?doc values 呢?
(1)我們首先關(guān)注如何激活 doc values,只要開啟 doc values 后,排序,分組,聚合的時候會自動使用 doc values 提速。在 ElasticSearch 中,doc values 默認(rèn)是開啟的,比較簡單暴力,我們也可以酌情關(guān)閉一些不需要使用 doc values 的字段,以節(jié)省磁盤空間,只需要設(shè)置 doc_values 為 false 就可以了,如下:
“session_id”:{“type”:“string”,“index”:“not_analyzed”,“doc_values”:false}
(2)使用 docvalue_fields 的檢索指定的字段:文章來源:http://www.zghlxwxcb.cn/news/detail-727127.html
GET my-index-000001/_search
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"docvalue_fields": [
"user.id",
"http.response.*",
{
"field": "date",
"format": "epoch_millis"
}
]
}
ES搜索指定字段的不同方式,詳情請見官網(wǎng):https://www.elastic.co/guide/en/elasticsearch/reference/7.x/search-fields.html#search-fields
————————————————
版權(quán)聲明:本文為CSDN博主「張維鵬」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/a745233700/article/details/117915118文章來源地址http://www.zghlxwxcb.cn/news/detail-727127.html
到了這里,關(guān)于ElasticSearch搜索引擎:常用的存儲mapping配置項 與 doc_values詳細(xì)介紹的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!