hive文件存儲格式orc,parquet,avro對比

orc文件存儲格式

ORC文件也是以二進制方式列式存儲的,所以是不可以直接讀取,ORC文件也是自解析的,它包含許多的元數據,這些元數據都是同構ProtoBuffer進行序列化的。文件結構如下

  • ORC文件:保存在文件系統上的普通二進制文件,一個ORC文件中可以包含多個stripe,每一個stripe包含多條記錄,這些記錄按照列進行獨立存儲,對應到Parquet中的row group的概念。
  • 文件級元數據:包括文件的描述信息PostScript、文件meta信息(包括整個文件的統計信息)、所有stripe的信息和文件schema信息。
  • stripe:一組行形成一個stripe,每次讀取文件是以行組爲單位的,一般爲HDFS的塊大小,保存了每一列的索引和數據。
  • stripe元數據:保存stripe的位置、每一個列的在該stripe的統計信息以及所有的stream類型和位置。
  • row group:索引的最小單位,一個stripe中包含多個row group,默認爲10000個值組成。
  • stream:一個stream表示文件中一段有效的數據,包括索引和數據兩類。索引stream保存每一個row group的位置和統計信息,數據stream包括多種類型的數據,具體需要哪幾種是由該列類型和編碼方式決定。
create table if not exists orctest(
name string,
age int
)
stored AS orc tblproperties("orc.compress" = "snappy");
  • Orcfile指定TBLPROPERTIES (“orc.compress”=“ZLIB”) or (“orc.compress”=“SNAPPY”) or (“orc.compress”=“NONE”) and other ORC properties
  • hive中orc存儲對數據的update依靠的是orc的特性,而不是hive的特性
  • orc存儲格式不支持load data local inpath方式加載數據,只能從textfile中select數據insert 到orc表中
  • ORC文件使用兩級壓縮機制,首先將一個數據流使用流式編碼器進行編碼,然後使用一個可選的壓縮器對數據流進行進一步壓縮。 一個column可能保存在一個或多個數據流中.

parquet文件存儲格式

Parquet文件是以二進制方式列式存儲的,所以是不可以直接讀取的,文件中包括該文件的數據和元數據,因此Parquet格式文件是自解析的。在HDFS文件系統和Parquet文件中存在如下幾個概念。

  • HDFS塊(Block):它是HDFS上的最小的副本單位,HDFS會把一個Block存儲在本地的一個文件並且維護分散在不同的機器上的多個副本,通常情況下一個Block的大小爲256M、512M等。
  • HDFS文件(File):一個HDFS的文件,包括數據和元數據,數據分散存儲在多個Block中。
  • 行組(Row Group):按照行將數據物理上劃分爲多個單元,每一個行組包含一定的行數,在一個HDFS文件中至少存儲一個行組,Parquet讀寫的時候會將整個行組緩存在內存中,所以如果每一個行組的大小是由內存大的小決定的,例如記錄佔用空間比較小的Schema可以在每一個行組中存儲更多的行。
  • 列塊(Column Chunk):在一個行組中每一列保存在一個列塊中,行組中的所有列連續的存儲在這個行組文件中。一個列塊中的值都是相同類型的,不同的列塊可能使用不同的算法進行壓縮。
  • 頁(Page):每一個列塊劃分爲多個頁,一個頁是最小的編碼的單位,在同一個列塊的不同頁可能使用不同的編碼方式。
create table if not exists parquettest(
name string,
age int
)
ROW FORMAT SERDE 'parquet.hive.serde.ParquetHiveSerDe'  STORED AS     INPUTFORMAT "parquet.hive.DeprecatedParquetInputFormat"    OUTPUTFORMAT "parquet.hive.DeprecatedParquetOutputFormat";
  • 不需要建表指定壓縮方式,插入數據之前set parquet.compression=SNAPPY 或set parquet.compression=GZIP
  • 映射下推
說到列式存儲的優勢,映射下推是最突出的,它意味着在獲取表中原始數據時只需要掃描查詢中需要的列,由於每一列的所有值都是連續存儲的,所以分區取出每一列的所有值就可以實現TableScan算子,而避免掃描整個表文件內容。
在Parquet中原生就支持映射下推,執行查詢的時候可以通過Configuration傳遞需要讀取的列的信息,這些列必須是Schema的子集,映射每次會掃描一個Row Group的數據,然後一次性得將該Row Group裏所有需要的列的Cloumn Chunk都讀取到內存中,每次讀取一個Row Group的數據能夠大大降低隨機讀的次數,除此之外,Parquet在讀取的時候會考慮列是否連續,如果某些需要的列是存儲位置是連續的,那麼一次讀操作就可以把多個列的數據讀取到內存。
  • 謂詞下推
在數據庫之類的查詢系統中最常用的優化手段就是謂詞下推了,通過將一些過濾條件儘可能的在最底層執行可以減少每一層交互的數據量,從而提升性能,例如”select count(1) from A Join B on A.id = B.id where A.a > 10 and B.b < 100”SQL查詢中,在處理Join操作之前需要首先對A和B執行TableScan操作,然後再進行Join,再執行過濾,最後計算聚合函數返回,但是如果把過濾條件A.a > 10和B.b < 100分別移到A表的TableScan和B表的TableScan的時候執行,可以大大降低Join操作的輸入數據。
無論是行式存儲還是列式存儲,都可以在將過濾條件在讀取一條記錄之後執行以判斷該記錄是否需要返回給調用者,在Parquet做了更進一步的優化,優化的方法時對每一個Row Group的每一個Column Chunk在存儲的時候都計算對應的統計信息,包括該Column Chunk的最大值、最小值和空值個數。通過這些統計值和該列的過濾條件可以判斷該Row Group是否需要掃描。另外Parquet未來還會增加諸如Bloom Filter和Index等優化數據,更加有效的完成謂詞下推。
在使用Parquet的時候可以通過如下兩種策略提升查詢性能:1、類似於關係數據庫的主鍵,對需要頻繁過濾的列設置爲有序的,這樣在導入數據的時候會根據該列的順序存儲數據,這樣可以最大化的利用最大值、最小值實現謂詞下推。2、減小行組大小和頁大小,這樣增加跳過整個行組的可能性,但是此時需要權衡由於壓縮和編碼效率下降帶來的I/O負載。

avro文件存儲格式

  • Avro依賴模式(Schema)來實現數據結構定義。可以把模式理解爲Java的類,它定義每個實例的結構,可以包含哪些屬性。可以根據類來產生任意多個實例對象。對實例序列化操作時必須需要知道它的基本結構,也就需要參考類的信息。這裏,根據模式產生的Avro對象類似於類的實例對象。每次序列化/反序列化時都需要知道模式的具體結構。所以,在Avro可用的一些場景下,如文件存儲或是網絡通信,都需要模式與數據同時存在

  • Avro的模式主要由JSON對象來表示,它可能會有一些特定的屬性,用來描述某種類型(Type)的不同形式。Avro支持八種基本類型(Primitive Type)和六種混合類型(Complex Type)。基本類型可以由JSON字符串來表示。每種不同的混合類型有不同的屬性(Attribute)來定義,有些屬性是必須的,有些是可選的,如果需要的話,可以用JSON數組來存放多個JSON對象定義。在這幾種Avro定義的類型的支持下,可以由用戶來創造出豐富的數據結構來,支持用戶紛繁複雜的數據。

  • Avro支持兩種序列化編碼方式:二進制編碼和JSON編碼。使用二進制編碼會高效序列化,並且序列化後得到的結果會比較小;而JSON一般用於調試系統或是基於WEB的應用。對Avro數據序列化/反序列化時都需要對模式以深度優先(Depth-First),從左到右(Left-to-Right)的遍歷順序來執行。基本類型的序列化容易解決,混合類型的序列化會有很多不同規則。對於基本類型和混合類型的二進制編碼在文檔中規定,按照模式的解析順序依次排列字節。對於JSON編碼,聯合類型(Union Type)就與其它混合類型表現不一致。

  • Avro爲了便於MapReduce的處理定義了一種容器文件格式(Container File Format)。這樣的文件中只能有一種模式,所有需要存入這個文件的對象都需要按照這種模式以二進制編碼的形式寫入。對象在文件中以塊(Block)來組織,並且這些對象都是可以被壓縮的。塊和塊之間會存在同步標記符(Synchronization Marker),以便MapReduce方便地切割文件用於處理。

create table if not exists avrotest(
name string,
age int
)
stored AS avro;

或者
CREATE TABLE kst
  PARTITIONED BY (ds string)
  ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.avro.AvroSerDe'
  STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat'
  OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat'
  TBLPROPERTIES (
    'avro.schema.url'='http://schema_provider/kst.avsc');
  • 高版本的hive,可以直接使用avro格式存儲,而不需要手動指定avro的schema文件,hive自己會根據table的創建方式自行解析並將schema存儲到文件的頭部

parquet,avro,orc存儲格式對比

  • 相同點
基於Hadoop文件系統優化出的存儲結構
提供高效的壓縮
二進制存儲格式
文件可分割,具有很強的伸縮性和並行處理能力
使用schema進行自我描述
屬於線上格式,可以在Hadoop節點之間傳遞數據
  • 不同點
1.行式存儲or列式存儲:Parquet和ORC都以列的形式存儲數據,而Avro以基於行的格式存儲數據。 就其本質而言,面向列的數據存儲針對讀取繁重的分析工作負載進行了優化,而基於行的數據庫最適合於大量寫入的事務性工作負載。
2.壓縮率:基於列的存儲區Parquet和ORC提供的壓縮率高於基於行的Avro格式。 
3.可兼容的平臺:ORC常用於Hive、Presto;Parquet常用於Impala、Drill、Spark、Arrow;Avro常用於Kafka、Druid。

在這裏插入圖片描述

ORC、Parquet的列式存儲格式的優勢

1、更高的壓縮比,由於相同類型的數據更容易針對不同類型的列使用高效的編碼和壓縮方式。
2、更小的I/O操作,由於映射下推和謂詞下推的使用,可以減少一大部分不必要的數據掃描,
尤其是表結構比較龐大的時候更加明顯,由此也能夠帶來更好的查詢性能
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章