㈠ ElasticSearch數據存儲內容
很多使用Elasticsearch的同學會關心數據存儲在ES中的存儲容量,會有這樣的疑問:xxTB的數據入到ES會使用多少存儲空間。這個問題其實很難直接回答的,只有數據寫入ES後,才能觀察到實際的存儲空間。比如同樣是1TB的數據,寫入ES的存儲空間可能差距會非常大,可能小到只有300~400GB,也可能多到6-7TB,為什麼會造成這么大的差距呢?究其原因,我們來探究下Elasticsearch中的數據是如何存儲。文章中我以Elasticsearch 2.3版本為示例,對應的lucene版本是5.5,Elasticsearch現在已經來到了6.5版本,數字類型、列存等存儲結構有些變化,但基本的概念變化不多,文章中的內容依然適用。
Elasticsearch對外提供的是index的概念,可以類比為DB,用戶查詢是在index上完成的,每個index由若干個shard組成,以此來達到分布式可擴展的能力。比如下圖是一個由10個shard組成的index。
shard是Elasticsearch數據存儲的最小單位,index的存儲容量為所有shard的存儲容量之和。Elasticsearch集群的存儲容量則為所有index存儲容量之和。
一個shard就對應了一個lucene的library。對於一個shard,Elasticsearch增加了translog的功能,類似於HBase WAL,是數據寫入過程中的中間數據,其餘的數據都在lucene庫中管理的。
所以Elasticsearch索引使用的存儲內容主要取決於lucene中的數據存儲。
下面我們主要看下lucene的文件內容,在了解lucene文件內容前,大家先了解些lucene的基本概念。
lucene包的文件是由很多segment文件組成的,segments_xxx文件記錄了lucene包下面的segment文件數量。每個segment會包含如下的文件。
下面我們以真實的數據作為示例,看看lucene中各類型數據的容量佔比。
寫100w數據,有一個uuid欄位,寫入的是長度為36位的uuid,字元串總為3600w位元組,約為35M。
數據使用一個shard,不帶副本,使用默認的壓縮演算法,寫入完成後merge成一個segment方便觀察。
使用線上默認的配置,uuid存為不分詞的字元串類型。創建如下索引:
首先寫入100w不同的uuid,使用磁碟容量細節如下:
可以看到正排數據、倒排索引數據,列存數據容量佔比幾乎相同,正排數據和倒排數據還會存儲Elasticsearch的唯一id欄位,所以容量會比列存多一些。
35M的uuid存入Elasticsearch後,數據膨脹了3倍,達到了122.7mb。Elasticsearch竟然這么消耗資源,不要著急下結論,接下來看另一個測試結果。
我們寫入100w一樣的uuid,然後看看Elasticsearch使用的容量。
這回35M的數據Elasticsearch容量只有13.2mb,其中還有主要的佔比還是Elasticsearch的唯一id,100w的uuid幾乎不佔存儲容積。
所以在Elasticsearch中建立索引的欄位如果基數越大(count distinct),越佔用磁碟空間。
我們再看看存100w個不一樣的整型會是如何。
從結果可以看到,100w整型數據,Elasticsearch的存儲開銷為13.6mb。如果以int型計算100w數據的長度的話,為400w位元組,大概是3.8mb數據。忽略Elasticsearch唯一id欄位的影響,Elasticsearch實際存儲容量跟整型數據長度差不多。
我們再看一下開啟最佳壓縮參數對存儲空間的影響:
結果中可以發現,只有正排數據會啟動壓縮,壓縮能力確實強勁,不考慮唯一id欄位,存儲容量大概壓縮到接近50%。
我們還做了一些實驗,Elasticsearch默認是開啟_all參數的,_all可以讓用戶傳入的整體json數據作為全文檢索的欄位,可以更方便的檢索,但在現實場景中已經使用的不多,相反會增加很多存儲容量的開銷,可以看下開啟_all的磁碟空間使用情況:
開啟_all比不開啟多了40mb的存儲空間,多的數據都在倒排索引上,大約會增加30%多的存儲開銷。所以線上都直接禁用。
然後我還做了其他幾個嘗試,為了驗證存儲容量是否和數據量成正比,寫入1000w數據的uuid,發現存儲容量基本為100w數據的10倍。我還驗證了數據長度是否和數據量成正比,發現把uuid增長2倍、4倍,存儲容量也響應的增加了2倍和4倍。在此就不一一列出數據了。
文件名為:segments_xxx
該文件為lucene數據文件的元信息文件,記錄所有segment的元數據信息。
該文件主要記錄了目前有多少segment,每個segment有一些基本信息,更新這些信息定位到每個segment的元信息文件。
lucene元信息文件還支持記錄userData,Elasticsearch可以在此記錄translog的一些相關信息。
文件後綴:.si
每個segment都有一個.si文件,記錄了該segment的元信息。
segment元信息文件中記錄了segment的文檔數量,segment對應的文件列表等信息。
文件後綴:.fnm
該文件存儲了fields的基本信息。
fields信息中包括field的數量,field的類型,以及IndexOpetions,包括是否存儲、是否索引,是否分詞,是否需要列存等等。
文件後綴:.fdx, .fdt
索引文件為.fdx,數據文件為.fdt,數據存儲文件功能為根據自動的文檔id,得到文檔的內容,搜索引擎的術語習慣稱之為正排數據,即doc_id -> content,es的_source數據就存在這
索引文件記錄了快速定位文檔數據的索引信息,數據文件記錄了所有文檔id的具體內容。
索引後綴:.tip,.tim
倒排索引也包含索引文件和數據文件,.tip為索引文件,.tim為數據文件,索引文件包含了每個欄位的索引元信息,數據文件有具體的索引內容。
5.5.0版本的倒排索引實現為FST tree,FST tree的最大優勢就是內存空間佔用非常低 ,具體可以參看下這篇文章: http://www.cnblogs.com/bonelee/p/6226185.html
http://examples.mikemccandless.com/fst.py?terms=&cmd=Build+it 為FST圖實例,可以根據輸入的數據構造出FST圖
生成的 FST 圖為:
文件後綴:.doc, .pos, .pay
.doc保存了每個term的doc id列表和term在doc中的詞頻
全文索引的欄位,會有.pos文件,保存了term在doc中的位置
全文索引的欄位,使用了一些像payloads的高級特性才會有.pay文件,保存了term在doc中的一些高級特性
文件後綴:.dvm, .dvd
索引文件為.dvm,數據文件為.dvd。
lucene實現的docvalues有如下類型:
其中SORTED_SET 的 SORTED_SINGLE_VALUED類型包括了兩類數據 : binary + numeric, binary是按ord排序的term的列表,numeric是doc到ord的映射。
㈡ es數據存儲在內存還是磁碟
磁碟
ES的數據存儲在磁碟中,數據操作在內存中。