日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

两种列式存储格式:Parquet和ORC

發(fā)布時間:2024/7/23 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 两种列式存储格式:Parquet和ORC 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

背景

隨著大數(shù)據(jù)時代的到來,越來越多的數(shù)據(jù)流向了Hadoop生態(tài)圈,同時對于能夠快速的從TB甚至PB級別的數(shù)據(jù)中獲取有價值的數(shù)據(jù)對于一個產(chǎn)品和公司來說更加重要,在Hadoop生態(tài)圈的快速發(fā)展過程中,涌現(xiàn)了一批開源的數(shù)據(jù)分析引擎,例如Hive、Spark SQL、Impala、Presto等,同時也產(chǎn)生了多個高性能的列式存儲格式,例如RCFile、ORC、Parquet等,本文主要從實現(xiàn)的角度上對比分析ORC和Parquet兩種典型的列存格式,并對它們做了相應(yīng)的對比測試。

列式存儲

由于OLAP查詢的特點,列式存儲可以提升其查詢性能,但是它是如何做到的呢?這就要從列式存儲的原理說起,從圖1中可以看到,相對于關(guān)系數(shù)據(jù)庫中通常使用的行式存儲,在使用列式存儲時每一列的所有元素都是順序存儲的。由此特點可以給查詢帶來如下的優(yōu)化:

  • 查詢的時候不需要掃描全部的數(shù)據(jù),而只需要讀取每次查詢涉及的列,這樣可以將I/O消耗降低N倍,另外可以保存每一列的統(tǒng)計信息(min、max、sum等),實現(xiàn)部分的謂詞下推。
  • 由于每一列的成員都是同構(gòu)的,可以針對不同的數(shù)據(jù)類型使用更高效的數(shù)據(jù)壓縮算法,進(jìn)一步減小I/O。
  • 由于每一列的成員的同構(gòu)性,可以使用更加適合CPU pipeline的編碼方式,減小CPU的緩存失效。

?

?

圖1 行式存儲VS列式存儲

?

嵌套數(shù)據(jù)格式

通常我們使用關(guān)系數(shù)據(jù)庫存儲結(jié)構(gòu)化數(shù)據(jù),而關(guān)系數(shù)據(jù)庫支持的數(shù)據(jù)模型都是扁平式的,而遇到諸如List、Map和自定義Struct的時候就需要用戶自己解析,但是在大數(shù)據(jù)環(huán)境下,數(shù)據(jù)的來源多種多樣,例如埋點數(shù)據(jù),很可能需要把程序中的某些對象內(nèi)容作為輸出的一部分,而每一個對象都可能是嵌套的,所以如果能夠原生的支持這種數(shù)據(jù),查詢的時候就不需要額外的解析便能獲得想要的結(jié)果。例如在Twitter,他們一個典型的日志對象(一條記錄)有87個字段,其中嵌套了7層,如下圖。

?

?

圖2 嵌套數(shù)據(jù)模型

?

隨著嵌套格式的數(shù)據(jù)的需求日益增加,目前Hadoop生態(tài)圈中主流的查詢引擎都支持更豐富的數(shù)據(jù)類型,例如Hive、SparkSQL、Impala等都原生的支持諸如struct、map、array這樣的復(fù)雜數(shù)據(jù)類型,這樣促使各種存儲格式都需要支持嵌套數(shù)據(jù)格式。

Parquet存儲格式

Apache Parquet是Hadoop生態(tài)圈中一種新型列式存儲格式,它可以兼容Hadoop生態(tài)圈中大多數(shù)計算框架(Mapreduce、Spark等),被多種查詢引擎支持(Hive、Impala、Drill等),并且它是語言和平臺無關(guān)的。Parquet最初是由Twitter和Cloudera合作開發(fā)完成并開源,2015年5月從Apache的孵化器里畢業(yè)成為Apache頂級項目。

Parquet最初的靈感來自Google于2010年發(fā)表的Dremel論文,文中介紹了一種支持嵌套結(jié)構(gòu)的存儲格式,并且使用了列式存儲的方式提升查詢性能,在Dremel論文中還介紹了Google如何使用這種存儲格式實現(xiàn)并行查詢的,如果對此感興趣可以參考論文和開源實現(xiàn)Drill。

數(shù)據(jù)模型

Parquet支持嵌套的數(shù)據(jù)模型,類似于Protocol Buffers,每一個數(shù)據(jù)模型的schema包含多個字段,每一個字段有三個屬性:重復(fù)次數(shù)、數(shù)據(jù)類型和字段名,重復(fù)次數(shù)可以是以下三種:required(只出現(xiàn)1次),repeated(出現(xiàn)0次或多次),optional(出現(xiàn)0次或1次)。每一個字段的數(shù)據(jù)類型可以分成兩種:group(復(fù)雜類型)和primitive(基本類型)。例如Dremel中提供的Document的schema示例,它的定義如下:

message Document {required int64 DocId;optional group Links {repeated int64 Backward;repeated int64 Forward; }repeated group Name {repeated group Language {required string Code;optional string Country; }optional string Url; } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

可以把這個Schema轉(zhuǎn)換成樹狀結(jié)構(gòu),根節(jié)點可以理解為repeated類型,如圖3。

?

?

圖3 Parquet的schema結(jié)構(gòu)

?

可以看出在Schema中所有的基本類型字段都是葉子節(jié)點,在這個Schema中一共存在6個葉子節(jié)點,如果把這樣的Schema轉(zhuǎn)換成扁平式的關(guān)系模型,就可以理解為該表包含六個列。Parquet中沒有Map、Array這樣的復(fù)雜數(shù)據(jù)結(jié)構(gòu),但是可以通過repeated和group組合來實現(xiàn)的。由于一條記錄中某一列可能出現(xiàn)零次或者多次,需要標(biāo)示出哪些列的值構(gòu)成一條完整的記錄。這是由Striping/Assembly算法實現(xiàn)的。

由于Parquet支持的數(shù)據(jù)模型比較松散,可能一條記錄中存在比較深的嵌套關(guān)系,如果為每一條記錄都維護(hù)一個類似的樹狀結(jié)可能會占用較大的存儲空間,因此Dremel論文中提出了一種高效的對于嵌套數(shù)據(jù)格式的壓縮算法:Striping/Assembly算法。它的原理是每一個記錄中的每一個成員值有三部分組成:Value、Repetition level和Definition level。value記錄了該成員的原始值,可以根據(jù)特定類型的壓縮算法進(jìn)行壓縮,兩個level值用于記錄該值在整個記錄中的位置。對于repeated類型的列,Repetition level值記錄了當(dāng)前值屬于哪一條記錄以及它處于該記錄的什么位置;對于repeated和optional類型的列,可能一條記錄中某一列是沒有值的,假設(shè)我們不記錄這樣的值就會導(dǎo)致本該屬于下一條記錄的值被當(dāng)做當(dāng)前記錄的一部分,從而造成數(shù)據(jù)的錯誤,因此對于這種情況需要一個占位符標(biāo)示這種情況。

通過Striping/Assembly算法,parquet可以使用較少的存儲空間表示復(fù)雜的嵌套格式,并且通常Repetition level和Definition level都是較小的整數(shù)值,可以通過RLE算法對其進(jìn)行壓縮,進(jìn)一步降低存儲空間。

文件結(jié)構(gòu)

Parquet文件是以二進(jìn)制方式存儲的,是不可以直接讀取和修改的,Parquet文件是自解析的,文件中包括該文件的數(shù)據(jù)和元數(shù)據(jù)。在HDFS文件系統(tǒng)和Parquet文件中存在如下幾個概念:

  • HDFS塊(Block):它是HDFS上的最小的副本單位,HDFS會把一個Block存儲在本地的一個文件并且維護(hù)分散在不同的機(jī)器上的多個副本,通常情況下一個Block的大小為256M、512M等。
  • HDFS文件(File):一個HDFS的文件,包括數(shù)據(jù)和元數(shù)據(jù),數(shù)據(jù)分散存儲在多個Block中。
  • 行組(Row Group):按照行將數(shù)據(jù)物理上劃分為多個單元,每一個行組包含一定的行數(shù),在一個HDFS文件中至少存儲一個行組,Parquet讀寫的時候會將整個行組緩存在內(nèi)存中,所以如果每一個行組的大小是由內(nèi)存大的小決定的。
  • 列塊(Column Chunk):在一個行組中每一列保存在一個列塊中,行組中的所有列連續(xù)的存儲在這個行組文件中。不同的列塊可能使用不同的算法進(jìn)行壓縮。
  • 頁(Page):每一個列塊劃分為多個頁,一個頁是最小的編碼的單位,在同一個列塊的不同頁可能使用不同的編碼方式。

通常情況下,在存儲Parquet數(shù)據(jù)的時候會按照HDFS的Block大小設(shè)置行組的大小,由于一般情況下每一個Mapper任務(wù)處理數(shù)據(jù)的最小單位是一個Block,這樣可以把每一個行組由一個Mapper任務(wù)處理,增大任務(wù)執(zhí)行并行度。Parquet文件的格式如下圖所示。

?

?

圖4 Parquet文件結(jié)構(gòu)

?

上圖展示了一個Parquet文件的結(jié)構(gòu),一個文件中可以存儲多個行組,文件的首位都是該文件的Magic Code,用于校驗它是否是一個Parquet文件,Footer length存儲了文件元數(shù)據(jù)的大小,通過該值和文件長度可以計算出元數(shù)據(jù)的偏移量,文件的元數(shù)據(jù)中包括每一個行組的元數(shù)據(jù)信息和當(dāng)前文件的Schema信息。除了文件中每一個行組的元數(shù)據(jù),每一頁的開始都會存儲該頁的元數(shù)據(jù),在Parquet中,有三種類型的頁:數(shù)據(jù)頁、字典頁和索引頁。數(shù)據(jù)頁用于存儲當(dāng)前行組中該列的值,字典頁存儲該列值的編碼字典,每一個列塊中最多包含一個字典頁,索引頁用來存儲當(dāng)前行組下該列的索引,目前Parquet中還不支持索引頁,但是在后面的版本中增加。

數(shù)據(jù)訪問

說到列式存儲的優(yōu)勢,Project下推是無疑最突出的,它意味著在獲取表中原始數(shù)據(jù)時只需要掃描查詢中需要的列,由于每一列的所有值都是連續(xù)存儲的,避免掃描整個表文件內(nèi)容。

在Parquet中原生就支持Project下推,執(zhí)行查詢的時候可以通過Configuration傳遞需要讀取的列的信息,這些列必須是Schema的子集,Parquet每次會掃描一個Row Group的數(shù)據(jù),然后一次性得將該Row Group里所有需要的列的Cloumn Chunk都讀取到內(nèi)存中,每次讀取一個Row Group的數(shù)據(jù)能夠大大降低隨機(jī)讀的次數(shù),除此之外,Parquet在讀取的時候會考慮列是否連續(xù),如果某些需要的列是存儲位置是連續(xù)的,那么一次讀操作就可以把多個列的數(shù)據(jù)讀取到內(nèi)存。

在數(shù)據(jù)訪問的過程中,Parquet還可以利用每一個row group生成的統(tǒng)計信息進(jìn)行謂詞下推,這部分信息包括該Column Chunk的最大值、最小值和空值個數(shù)。通過這些統(tǒng)計值和該列的過濾條件可以判斷該Row Group是否需要掃描。另外Parquet未來還會增加諸如Bloom Filter和Index等優(yōu)化數(shù)據(jù),更加有效的完成謂詞下推。

ORC文件格式

ORC文件格式是一種Hadoop生態(tài)圈中的列式存儲格式,它的產(chǎn)生早在2013年初,最初產(chǎn)生自Apache Hive,用于降低Hadoop數(shù)據(jù)存儲空間和加速Hive查詢速度。和Parquet類似,它并不是一個單純的列式存儲格式,仍然是首先根據(jù)行組分割整個表,在每一個行組內(nèi)進(jìn)行按列存儲。ORC文件是自描述的,它的元數(shù)據(jù)使用Protocol Buffers序列化,并且文件中的數(shù)據(jù)盡可能的壓縮以降低存儲空間的消耗,目前也被Spark SQL、Presto等查詢引擎支持,但是Impala對于ORC目前沒有支持,仍然使用Parquet作為主要的列式存儲格式。2015年ORC項目被Apache項目基金會提升為Apache頂級項目。

數(shù)據(jù)模型

和Parquet不同,ORC原生是不支持嵌套數(shù)據(jù)格式的,而是通過對復(fù)雜數(shù)據(jù)類型特殊處理的方式實現(xiàn)嵌套格式的支持,例如對于如下的hive表:

CREATE TABLE `orcStructTable`(`name` string,`course` struct<course:string,score:int>,`score` map<string,int>,`work_locations` array<string>)
  • 1
  • 2
  • 3
  • 4
  • 5

ORC格式會將其轉(zhuǎn)換成如下的樹狀結(jié)構(gòu):

圖5 ORC的schema結(jié)構(gòu)

?

在ORC的結(jié)構(gòu)中這個schema包含10個column,其中包含了復(fù)雜類型列和原始類型的列,前者包括LIST、STRUCT、MAP和UNION類型,后者包括BOOLEAN、整數(shù)、浮點數(shù)、字符串類型等,其中STRUCT的孩子節(jié)點包括它的成員變量,可能有多個孩子節(jié)點,MAP有兩個孩子節(jié)點,分別為key和value,LIST包含一個孩子節(jié)點,類型為該LIST的成員類型,UNION一般不怎么用得到。每一個Schema樹的根節(jié)點為一個Struct類型,所有的column按照樹的中序遍歷順序編號。

ORC只需要存儲schema樹中葉子節(jié)點的值,而中間的非葉子節(jié)點只是做一層代理,它們只需要負(fù)責(zé)孩子節(jié)點值得讀取,只有真正的葉子節(jié)點才會讀取數(shù)據(jù),然后交由父節(jié)點封裝成對應(yīng)的數(shù)據(jù)結(jié)構(gòu)返回。

文件結(jié)構(gòu)

和Parquet類似,ORC文件也是以二進(jìn)制方式存儲的,所以是不可以直接讀取,ORC文件也是自解析的,它包含許多的元數(shù)據(jù),這些元數(shù)據(jù)都是同構(gòu)ProtoBuffer進(jìn)行序列化的。ORC的文件結(jié)構(gòu)入圖6,其中涉及到如下的概念:

  • ORC文件:保存在文件系統(tǒng)上的普通二進(jìn)制文件,一個ORC文件中可以包含多個stripe,每一個stripe包含多條記錄,這些記錄按照列進(jìn)行獨立存儲,對應(yīng)到Parquet中的row group的概念。
  • 文件級元數(shù)據(jù):包括文件的描述信息PostScript、文件meta信息(包括整個文件的統(tǒng)計信息)、所有stripe的信息和文件schema信息。
  • stripe:一組行形成一個stripe,每次讀取文件是以行組為單位的,一般為HDFS的塊大小,保存了每一列的索引和數(shù)據(jù)。
  • stripe元數(shù)據(jù):保存stripe的位置、每一個列的在該stripe的統(tǒng)計信息以及所有的stream類型和位置。
  • row group:索引的最小單位,一個stripe中包含多個row group,默認(rèn)為10000個值組成。
  • stream:一個stream表示文件中一段有效的數(shù)據(jù),包括索引和數(shù)據(jù)兩類。索引stream保存每一個row group的位置和統(tǒng)計信息,數(shù)據(jù)stream包括多種類型的數(shù)據(jù),具體需要哪幾種是由該列類型和編碼方式?jīng)Q定。

?

?

圖6 ORC文件結(jié)構(gòu)

?

在ORC文件中保存了三個層級的統(tǒng)計信息,分別為文件級別、stripe級別和row group級別的,他們都可以用來根據(jù)Search ARGuments(謂詞下推條件)判斷是否可以跳過某些數(shù)據(jù),在統(tǒng)計信息中都包含成員數(shù)和是否有null值,并且對于不同類型的數(shù)據(jù)設(shè)置一些特定的統(tǒng)計信息。

數(shù)據(jù)訪問

讀取ORC文件是從尾部開始的,第一次讀取16KB的大小,盡可能的將Postscript和Footer數(shù)據(jù)都讀入內(nèi)存。文件的最后一個字節(jié)保存著PostScript的長度,它的長度不會超過256字節(jié),PostScript中保存著整個文件的元數(shù)據(jù)信息,它包括文件的壓縮格式、文件內(nèi)部每一個壓縮塊的最大長度(每次分配內(nèi)存的大小)、Footer長度,以及一些版本信息。在Postscript和Footer之間存儲著整個文件的統(tǒng)計信息(上圖中未畫出),這部分的統(tǒng)計信息包括每一個stripe中每一列的信息,主要統(tǒng)計成員數(shù)、最大值、最小值、是否有空值等。

接下來讀取文件的Footer信息,它包含了每一個stripe的長度和偏移量,該文件的schema信息(將schema樹按照schema中的編號保存在數(shù)組中)、整個文件的統(tǒng)計信息以及每一個row group的行數(shù)。

處理stripe時首先從Footer中獲取每一個stripe的其實位置和長度、每一個stripe的Footer數(shù)據(jù)(元數(shù)據(jù),記錄了index和data的的長度),整個striper被分為index和data兩部分,stripe內(nèi)部是按照row group進(jìn)行分塊的(每一個row group中多少條記錄在文件的Footer中存儲),row group內(nèi)部按列存儲。每一個row group由多個stream保存數(shù)據(jù)和索引信息。每一個stream的數(shù)據(jù)會根據(jù)該列的類型使用特定的壓縮算法保存。在ORC中存在如下幾種stream類型:

  • PRESENT:每一個成員值在這個stream中保持一位(bit)用于標(biāo)示該值是否為NULL,通過它可以只記錄部位NULL的值
  • DATA:該列的中屬于當(dāng)前stripe的成員值。
  • LENGTH:每一個成員的長度,這個是針對string類型的列才有的。
  • DICTIONARY_DATA:對string類型數(shù)據(jù)編碼之后字典的內(nèi)容。
  • SECONDARY:存儲Decimal、timestamp類型的小數(shù)或者納秒數(shù)等。
  • ROW_INDEX:保存stripe中每一個row group的統(tǒng)計信息和每一個row group起始位置信息。

在初始化階段獲取全部的元數(shù)據(jù)之后,可以通過includes數(shù)組指定需要讀取的列編號,它是一個boolean數(shù)組,如果不指定則讀取全部的列,還可以通過傳遞SearchArgument參數(shù)指定過濾條件,根據(jù)元數(shù)據(jù)首先讀取每一個stripe中的index信息,然后根據(jù)index中統(tǒng)計信息以及SearchArgument參數(shù)確定需要讀取的row group編號,再根據(jù)includes數(shù)據(jù)決定需要從這些row group中讀取的列,通過這兩層的過濾需要讀取的數(shù)據(jù)只是整個stripe多個小段的區(qū)間,然后ORC會盡可能合并多個離散的區(qū)間盡可能的減少I/O次數(shù)。然后再根據(jù)index中保存的下一個row group的位置信息調(diào)至該stripe中第一個需要讀取的row group中。

由于ORC中使用了更加精確的索引信息,使得在讀取數(shù)據(jù)時可以指定從任意一行開始讀取,更細(xì)粒度的統(tǒng)計信息使得讀取ORC文件跳過整個row group,ORC默認(rèn)會對任何一塊數(shù)據(jù)和索引信息使用ZLIB壓縮,因此ORC文件占用的存儲空間也更小,這點在后面的測試對比中也有所印證。

在新版本的ORC中也加入了對Bloom Filter的支持,它可以進(jìn)一步提升謂詞下推的效率,在Hive 1.2.0版本以后也加入了對此的支持。

性能測試

為了對比測試兩種存儲格式,我選擇使用TPC-DS數(shù)據(jù)集并且對它進(jìn)行改造以生成寬表、嵌套和多層嵌套的數(shù)據(jù)。使用最常用的Hive作為SQL引擎進(jìn)行測試。

測試環(huán)境

  • Hadoop集群:物理測試集群,四臺DataNode/NodeManager機(jī)器,每個機(jī)器32core+128GB,測試時使用整個集群的資源。
  • Hive:Hive 1.2.1版本,使用hiveserver2啟動,本機(jī)MySql作為元數(shù)據(jù)庫,jdbc方式提交查詢SQL
  • 數(shù)據(jù)集:100GB TPC-DS數(shù)據(jù)集,選取其中的Store_Sales為事實表的模型作為測試數(shù)據(jù)
  • 查詢SQL:選擇TPC-DS中涉及到上述模型的10條SQL并對其進(jìn)行改造。

測試場景和結(jié)果

整個測試設(shè)置了四種場景,每一種場景下對比測試數(shù)據(jù)占用的存儲空間的大小和相同查詢執(zhí)行消耗的時間對比,除了場景一基于原始的TPC-DS數(shù)據(jù)集外,其余的數(shù)據(jù)都需要進(jìn)行數(shù)據(jù)導(dǎo)入,同時對比這幾個場景的數(shù)據(jù)導(dǎo)入時間。

場景一:一個事實表、多個維度表,復(fù)雜的join查詢。

基于原始的TPC-DS數(shù)據(jù)集。

Store_Sales表記錄數(shù):287,997,024,表大小為:

  • 原始Text格式,未壓縮 : 38.1 G
  • ORC格式,默認(rèn)壓縮(ZLIB),一共1800+個分區(qū) : 11.5 G
  • Parquet格式,默認(rèn)壓縮(Snappy),一共1800+個分區(qū) : 14.8 G

查詢測試結(jié)果:

?

?

場景二:維度表和事實表join之后生成的寬表,只在一個表上做查詢。

整個測試設(shè)置了四種場景,每一種場景下對比測試數(shù)據(jù)占用的存儲空間的大小和相同查詢執(zhí)行消耗的時間對比,除了場景一基于原始的TPC-DS數(shù)據(jù)集外,其余的數(shù)據(jù)都需要進(jìn)行數(shù)據(jù)導(dǎo)入,同時對比這幾個場景的數(shù)據(jù)導(dǎo)入時間。選取數(shù)據(jù)模型中的store_sales, household_demographics, customer_address, date_dim, store表生成一個扁平式寬表(store_sales_wide_table),基于這個表執(zhí)行查詢,由于場景一種選擇的query大多數(shù)不能完全match到這個寬表,所以對場景1中的SQL進(jìn)行部分改造。

store_sales_wide_table表記錄數(shù):263,704,266,表大小為:

  • 原始Text格式,未壓縮 : 149.0 G
  • ORC格式,默認(rèn)壓縮 : 10.6 G
  • PARQUET格式,默認(rèn)壓縮 : 12.5 G

查詢測試結(jié)果:

?

?

場景三:復(fù)雜的數(shù)據(jù)結(jié)構(gòu)組成的寬表,struct、list、map等(1層)

整個測試設(shè)置了四種場景,每一種場景下對比測試數(shù)據(jù)占用的存儲空間的大小和相同查詢執(zhí)行消耗的時間對比,除了場景一基于原始的TPC-DS數(shù)據(jù)集外,其余的數(shù)據(jù)都需要進(jìn)行數(shù)據(jù)導(dǎo)入,同時對比這幾個場景的數(shù)據(jù)導(dǎo)入時間。在場景二的基礎(chǔ)上,將維度表(除了store_sales表)轉(zhuǎn)換成一個struct或者map對象,源store_sales表中的字段保持不變。生成有一層嵌套的新表(store_sales_wide_table_one_nested),使用的查詢邏輯相同。

store_sales_wide_table_one_nested表記錄數(shù):263,704,266,表大小為:

  • 原始Text格式,未壓縮 : 245.3 G
  • ORC格式,默認(rèn)壓縮 : 10.9 G 比store_sales表還小?
  • PARQUET格式,默認(rèn)壓縮 : 29.8 G

查詢測試結(jié)果:

?

?

場景四:復(fù)雜的數(shù)據(jù)結(jié)構(gòu),多層嵌套。(3層)

整個測試設(shè)置了四種場景,每一種場景下對比測試數(shù)據(jù)占用的存儲空間的大小和相同查詢執(zhí)行消耗的時間對比,除了場景一基于原始的TPC-DS數(shù)據(jù)集外,其余的數(shù)據(jù)都需要進(jìn)行數(shù)據(jù)導(dǎo)入,同時對比這幾個場景的數(shù)據(jù)導(dǎo)入時間。在場景三的基礎(chǔ)上,將部分維度表的struct內(nèi)的字段再轉(zhuǎn)換成struct或者map對象,只存在struct中嵌套map的情況,最深的嵌套為三層。生成一個多層嵌套的新表(store_sales_wide_table_more_nested),使用的查詢邏輯相同。

該場景中只涉及一個多層嵌套的寬表,沒有任何分區(qū)字段,store_sales_wide_table_more_nested表記錄數(shù):263,704,266,表大小為:

  • 原始Text格式,未壓縮 : 222.7 G
  • ORC格式,默認(rèn)壓縮 : 10.9 G 比store_sales表還小?
  • PARQUET格式,默認(rèn)壓縮 : 23.1 G 比一層嵌套表store_sales_wide_table_one_nested要小?

查詢測試結(jié)果:

?

?

結(jié)果分析

從上述測試結(jié)果來看,星狀模型對于數(shù)據(jù)分析場景并不是很合適,多個表的join會大大拖慢查詢速度,并且不能很好的利用列式存儲帶來的性能提升,在使用寬表的情況下,列式存儲的性能提升明顯,ORC文件格式在存儲空間上要遠(yuǎn)優(yōu)于Text格式,較之于PARQUET格式有一倍的存儲空間提升,在導(dǎo)數(shù)據(jù)(insert into table select 這樣的方式)方面ORC格式也要優(yōu)于PARQUET,在最終的查詢性能上可以看到,無論是無嵌套的扁平式寬表,或是一層嵌套表,還是多層嵌套的寬表,兩者的查詢性能相差不多,較之于Text格式有2到3倍左右的提升。

另外,通過對比場景二和場景三的測試結(jié)果,可以發(fā)現(xiàn)扁平式的表結(jié)構(gòu)要比嵌套式結(jié)構(gòu)的查詢性能有所提升,所以如果選擇使用大寬表,則設(shè)計寬表的時候盡可能的將表設(shè)計的扁平化,減少嵌套數(shù)據(jù)。

通過這三種文件存儲格式的測試對比,ORC文件存儲格式無論是在空間存儲、導(dǎo)數(shù)據(jù)速度還是查詢速度上表現(xiàn)的都較好一些,并且ORC可以一定程度上支持ACID操作,社區(qū)的發(fā)展目前也是Hive中比較提倡使用的一種列式存儲格式,另外,本次測試主要針對的是Hive引擎,所以不排除存在Hive與ORC的敏感度比PARQUET要高的可能性。

總結(jié)

本文主要從數(shù)據(jù)模型、文件格式和數(shù)據(jù)訪問流程等幾個方面詳細(xì)介紹了Hadoop生態(tài)圈中的兩種列式存儲格式——Parquet和ORC,并通過大數(shù)據(jù)量的測試對兩者的存儲和查詢性能進(jìn)行了對比。對于大數(shù)據(jù)場景下的數(shù)據(jù)分析需求,使用這兩種存儲格式總會帶來存儲和性能上的提升,但是在實際使用時還需要針對實際的數(shù)據(jù)進(jìn)行選擇。另外由于不同開源產(chǎn)品可能對不同的存儲格式有特定的優(yōu)化,所以選擇時還需要考慮查詢引擎的因素。

總結(jié)

以上是生活随笔為你收集整理的两种列式存储格式:Parquet和ORC的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲一区二区三区在线播放 | 中国av一区二区三区 | 无码人妻精品一区二区三区99不卡 | 成年人晚上看的视频 | 国产性精品 | 日韩精品一区二区三区中文在线 | 日韩成人免费观看 | 99久久婷婷 | 国产淫语对白 | 中文字幕一区二区三区手机版 | 黄色xxxxxx | 欧美爽爽爽 | 人妻一区二区三 | 欧美中文字幕在线观看 | 精品久久久中文字幕人妻 | 色av免费 | 亚洲九区 | 欧美做爰全过程免费看 | 伊在线久久丫 | 一区二区91 | 中文天堂在线视频 | 亚洲av无码国产精品永久一区 | 亚洲精品视频一区二区三区 | 亚洲自拍p | www.久久成人 | 快色视频| 亚洲精品久久久蜜桃 | 又黄又爽在线观看 | 一级片小视频 | 日韩中文字幕精品视频 | xxx国产 | 无码精品人妻一区二区三区湄公河 | 成人高清免费 | 蜜桃av噜噜 | 国产精品51 | 成人精品av | 久久久久久久久久艹 | 美女av免费看 | 欧美aa在线 | 日韩精品激情 | 久久久久夜夜夜精品国产 | 精品欧美一区二区精品久久 | 欧美成人午夜视频 | 国产天天射 | 韩国中文字幕 | 香港三级日本三级韩国三级 | 能看的av | 美女考逼| 日日射日日干 | h在线免费观看 | 午夜精品久久久久久99热 | 中文字幕精品无码亚 | 日韩激情视频在线观看 | 久久国产视频播放 | 亚洲一区二区黄片 | 亚洲大尺度网站 | 亚洲精品社区 | 黑人巨大精品欧美黑寡妇 | 成人av在线资源 | 韩国19主播内部福利vip | 亚洲av女人18毛片水真多 | 少妇久久久久久 | 天堂草在线观看 | 成人午夜视频在线播放 | 六月丁香激情 | av黄在线 | 欧美日韩在线a | 麻豆91精品91久久久 | 久久毛片网站 | 又粗又猛又爽又黄的视频 | 日韩午夜激情视频 | 日日射视频 | 黄色片在线免费看 | 久久大胆人体 | 亚洲另类av | 性xxxxxxxxx| 亚洲性猛交富婆 | 国产精品无码影院 | 中文字幕22页 | 插插射射| 午夜影院一区二区三区 | 精品久久久在线观看 | 久草黄色 | 亚洲av无码久久精品狠狠爱浪潮 | 欧美精品国产 | 亚洲国产精品久久久久久6q | 精品午夜福利视频 | 91黄色看片| 少妇无码吹潮 | 人妻久久一区二区 | 日韩午夜一区 | av一级黄色片 | 欧美日韩在线综合 | 成人av影视在线 | 色国产精品 | 久久香蕉网 | 一区二区播放 | 五月婷婷婷婷 | jizzjizz视频|