首頁 > 軟體

詳解hive常見表結構

2022-08-11 14:03:12

hive簡介

hive是基於Hadoop的一個資料倉儲工具,用來進行資料提取、轉化、載入,這是一種可以儲存、查詢和分析儲存在Hadoop中的大規模資料的機制。hive資料倉儲工具能將結構化的資料檔案對映為一張資料庫表,並提供SQL查詢功能,能將SQL語句轉變成MapReduce任務來執行。Hive的優點是學習成本低,可以通過類似SQL語句實現快速MapReduce統計,使MapReduce變得更加簡單,而不必開發專門的MapReduce應用程式。hive十分適合對資料倉儲進行統計分析。 [1]

1.外部表

當檔案已經存在或位於遠端位置時,我們可以使用外部表,外部表的儲存由自己指定。

特點:刪除表,資料依然存在

建表語句

CREATE EXTERNAL TABLE tmp_xx(id int,name String);

2.內部表

hive管理控制表的整個生命週期,儲存位置在hive.metastore.warehouse.dir目錄下。

特點:刪除表時,資料也被刪除

建表語句

CREATE TABLE tmp_xx(id int,name String);

3.分割區表

把一個表的資料以分割區欄位的值作為目錄去儲存。

特點:

  • 縮小了硬碟掃描資料的區域,減少磁碟IO
  • 將表資料儲存在多個分割區目錄,便於獨立管理(建立,刪除)資料

儲存結構如下

 

1.靜態分割區

在執行前就知道分割區的值

  • 可以根據PARTITIONED BY建立分割區表,一個表可以擁有一個或者多個分割區,每個分割區以資料夾的形式單獨存在表資料夾的目錄下。
  • 分割區是以欄位的形式在表結構中存在,通過describe table命令可以檢視到欄位存在,但是該欄位不存放實際的資料內容,僅僅是分割區的表示。
  • 分割區建表分為2種,一種是單分割區,也就是說在表資料夾目錄下只有一級資料夾目錄。另外一種是多分割區,表資料夾下出現多資料夾巢狀模式。

單分割區相關語法

#單分割區表建立
CREATE TABLE tmp_xx(id int,name String) partitioned by (d string);
 
#新增分割區
ALTER TABLE tmp_partition ADD IF NOT EXISTS PARTITION (d='20220628')
 
#刪除分割區
ALTER TABLE tmp_partition DROP IF EXISTS PARTITION (d='20220628')
 
#資料寫入
INSERT OVERWRITE TABLE tmp_xx PARTITION (d='20220629')
SELECT id, name FROM tmp_yy limit 10;
 
#檢視分割區資料
select * from tmp_xx where d='20220629'
 
#檢視表分割區
show partitions table;
 
#檢視目錄
hadoop dfs -du -h /user/hive/warehouse/tmp_xxx

多分割區相關語法

#多分割區表建立
CREATE TABLE tmp_xx(id int,name String) partitioned by (d String,h String);
 
#資料寫入
INSERT OVERWRITE TABLE tmp_xx PARTITION (d='20220629',h='15')
SELECT id, name FROM tmp_yy limit 10;
 
#檢視分割區資料
select * from tmp_xx where d='20220629' and h='15'

2.動態分割區

執行時才知道分割區的值,相比於靜態分割區可以一次寫入多個分割區資料,而不用在每次分割區寫入的時候一次執行多次insert,其他的地方和靜態分割區都是一樣的。

官方檔案:https://cwiki.apache.org/confluence/display/Hive/DynamicPartitions

特點:

  • 在INSERT … SELECT …查詢中,必須在SELECT語句中的列中最後指定動態分割區列,並按PARTITION()子句中出現的順序進行排列
  • 如果動態分割區和靜態分割區一起使用,必須是靜態分割區的欄位在前,動態分割區的欄位在後。

想要使用動態分割區需要hive開啟動態分割區,引數如下

set hive.exec.dynamic.partition=true;   --開啟動態分割區 預設為false,不開啟
set hive.exec.dynamic.partition.mode=nonstrict; --指定動態分割區模式,預設為strict
 
下面引數可選
SET hive.exec.max.dynamic.partitions=2048; 
SET hive.exec.max.dynamic.partitions.pernode=256; 
SET hive.exec.max.created.files=10000; 
SET hive.error.on.empty.partition=true;

語法:

#寫入資料
INSERT overwrite TABLE tmp_partition PARTITION(d)
SELECT id,NAME,d FROM tmp_xxx
 
#寫入多分割區資料
INSERT overwrite TABLE tmp_partition PARTITION(d,h)
SELECT id,NAME,d,h FROM tmp_xxx
 
#混合分割區使用,使用動態分割區和靜態分割區,靜態分割區必須在前
INSERT overwrite TABLE tmp_partition PARTITION(d='20220629',h)
SELECT id,NAME,h FROM tmp_xxx

4.分桶表

對比分割區表,分桶表是對資料進行更加細粒度的劃分。一般用的比較少,在資料量比較小的時候使用分桶表可能效能更差。

分桶表將整個資料內容按照分桶欄位的雜湊值進行區分,使用該雜湊值除以桶的個數得到取餘數,bucket_id = column.hashcode % bucket.num,餘數決定了該條記錄會被分在哪個桶中。餘數相同的記錄會分在一個桶裡。需要注意的是,在物理結構上,一個桶對應一個檔案,而分割區表只是一個目錄,至於目錄下有多少資料是不確定的。

分桶表和分割區表的區別

分割區表分桶表
儲存結構檔案目錄/資料夾
建立語句partitioned byclustered by,指定桶個數
數量分割區個數可增長分桶數指定後不在增長
用途避免掃描全表,通過分割區列指定查詢目錄提高查詢速度抽樣及大表join時提高效率

想要使用分桶表需要開啟分桶機制,預設開啟

set hive.enforce.bucketing=true

建表

CREATE TABLE tmp_bucket(id INT,NAME STRING) clustered BY (id) INTO 4 buckets

寫入資料之後檢視檔案結構,發現表資料夾下有4個檔案,說明分桶成功

 

1.抽樣

#建表
select columns from table tablesample(bucket x out of y on column);
-- x:表示從第幾個分桶進行抽樣
-- y:表示每隔幾個分桶取一個分桶,y必須為表bucket的整數倍或者因子
 
#從分桶表的建表語句中可知,我們一共分了4個桶,所以我們這裡x取1,y取2
一共抽取2(4/2)個桶,從第一個桶開始,每隔2個桶抽取一次,即第一個桶和
第三個桶。
SELECT id,NAME FROM tmp_bucket tablesample(bucket 1 OUT of 2 ON id) LIMIT 10

2.map-side join

獲得更高的查詢處理效率。桶為表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。

具體而言,連線兩個在(包含連線列的)相同列上劃分了桶的表,可以使用 Map 端連線 (Map-side join)高效的實現。比如JOIN操作。對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那麼將儲存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的資料量。

需要注意的是這種方式只適用於大表,小表不適用,表的大小至少得幾個G或幾個T,此功能未做測試。

5.表的檔案儲存格式

  • STORED AS 指定表的檔案儲存格式預設TEXT FILE(文字檔案)格式儲存,
  • 預設儲存格式可通過hive.default.fileformat設定修改
  • 其它常用儲存格式 Parquet(列式),Avro,ORC(列式),Sequence File,INPUT FORMAT & OUTPUT FORMAT (二進位制)

1.TEXTFILE

STORED AS INPUTFORMAT                              
   'org.apache.hadoop.mapred.TextInputFormat'       
 OUTPUTFORMAT                                       
   'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

純文字檔案儲存,TEXTFILE預設是hive的預設儲存方式,使用者可以通過設定 hive.default.fileformat 來修改。

在HDFS上可直接檢視資料,可結合Gzip、Bzip2使用(系統自動檢查,執行查詢時自動解壓),但是使用這種方式,hive不會對資料進行切分,無法對資料進行並行操作。

儲存方式:行儲存

優勢:可使用任意的分割符進行分割;在hdfs上可查可標記;載入速度較快;

劣勢:不會對資料進行壓縮處理,儲存空間較大、磁碟開銷大、資料解析開銷大。

2.SEQUENCEFILE

STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.SequenceFileInputFormat'
  OUTPUTFORMAT
  'org.apache.hadoop.mapred.SequenceFileOutputFormat'

儲存為壓縮的序列化檔案。是hadoop中的標準序列化檔案,可壓縮,可分塊。SequenceFile是一個由二進位制序列化過的key/value的位元組流組成的文字儲存檔案,它可以在map/reduce過程中的input/output 的format時被使用。

SequenceFile 有三種壓縮態:

  • Uncompressed – 未進行壓縮的狀
  • record compressed - 對每一條記錄的value值進行了壓縮(檔案頭中包含上使用哪種壓縮演演算法的資訊)
  • block compressed – 當資料量達到一定大小後,將停止寫入進行整體壓縮,整體壓縮的方法是把所有的keylength,key,vlength,value 分別合在一起進行整體壓縮,塊的壓縮效率要比記錄的壓縮效率高 hive中通過設定SET mapred.output.compression.type=BLOCK;來修改SequenceFile壓縮方式。

儲存方式:行儲存

優勢:儲存時候會對資料進行壓縮處理,儲存空間小;支援檔案切割分片;查詢速度比TestFile速度快;

劣勢:無法視覺化展示資料;不可以直接使用load命令對資料進行載入;自身的壓縮演算法佔用一定的空間

3.RCFILE

STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.RCFileInputFormat'
  OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.RCFileOutputFormat'

檔案儲存方式為二進位制檔案。以RcFile檔案格式儲存的表也會對資料進行壓縮處理,在HDFS上以二進位制格式儲存,不可直接檢視。

RCFILE是一種行列儲存相結合的儲存方式,該儲存結構遵循的是“先水平劃分,再垂直劃分”的設計裡面。首先,將資料按行分塊形成行組,這樣可以使同一行的資料在一個節點上。然後,把行組內的資料列式儲存,將列維度的資料進行壓縮,並提供了一種lazy解壓技術。

Rcfile在進行資料讀取時會順序處理HDFS塊中的每個行組,讀取行組的後設資料頭部和給定查詢需要的列,將其載入到記憶體中並進行解壓,直到處理下一個行組。但是,rcfile不會解壓所有的載入列,解壓採用lazy解壓技術,只有滿足where條件的列才會被解壓,減少了不必要的列解壓。

在rcfile中每一個行組的大小是可變的,預設行組大小為4MB。行組變大可以提升資料的壓縮效率,減少並行儲存量,但是在讀取資料時會佔用更多的記憶體,可能影響查詢效率和其他的並行查詢。使用者可根據具體機器和自身需要調整行組大小。

儲存方式:行列混合的儲存格式,將相近的行分塊後,每塊按列儲存。

優勢:基於列儲存,壓縮快且效率更高,;佔用的磁碟儲存空間小,讀取記錄時涉及的block少,IO小;查詢列時,讀取所需列只需讀取列所在塊的頭部定義,讀取速度快(在讀取全量資料時,效能與Sequence沒有明顯區別);

劣勢:無法視覺化展示資料;匯入資料時耗時較長;不能直接使用load命令對資料進行載入;自身的壓縮演算法佔用一定空間,但比SequenceFile所佔空間稍小;

4.ORC

ROW FORMAT SERDE
  'org.apache.hadoop.hive.ql.io.orc.OrcSerde'
  STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat'
  OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'

ORC (Optimized Record Columnar)是RC File 的改進,主要在壓縮編碼、查詢效能上進行了升級; ORC具備一些高階特性,如:update操作,支援ACID,支援struct、array複雜型別。Hive1.x版本後支援事務和update操作,就是基於ORC實現的(目前其他儲存格式暫不支援)。

儲存方式:按行組分割整個表,行組內進行列式儲存。資料按行分塊,每塊按照列儲存

檔案結構:

首先做一些名詞註釋:

ORC檔案:儲存在檔案系統上的普通二進位制檔案,一個ORC檔案中包含多個stripe,每個stripe包含多條記錄,這些記錄按照列進行獨立儲存。

檔案級後設資料:包括檔案的描述資訊postscript、檔案meta資訊(包括整個檔案的統計資訊)、所有的stripe的資訊和schema資訊。

Stripe:一組行形成一個stripe,每次讀取檔案是以行組為單位的,一般為hdfs的塊大小,儲存了每一列的索引和資料。

Stripe後設資料:儲存stripe的位置、每個列在該stripe的統計資訊以及所有的stream型別和位置。

Row group:索引的最小單位,一個stripe中包含多個row group,預設為10000個值組成。

Stream:一個stream表示檔案中的一段有效的資料,包括索引和資料。索引stream儲存每一個row group的位置和統計資訊,資料stream包括多種型別的資料,具體情況由該列型別和編碼方式決定。

在ORC檔案中儲存了三個層級的統計資訊,分別為檔案級別、stripe級別和row group級別,他們可以根據下發的搜尋引數判斷是否可以跳過某些資料。在這些統計資訊中包含成員數和是否有null值,且對不同型別的資料設定了特定統計資訊。

ORC的檔案結構如下:

 

檔案級別:

在ORC檔案的末尾記錄了檔案級別的統計資訊,包括整個檔案的列統計資訊。這些資訊主要是用於查詢的優化,也可以為一些簡單的聚合查詢如max、min、sum輸出結果。

Stripe級別:

保留行級別的統計資訊,用於判斷該Stripe中的記錄是否符合where中的條件,是否需要被讀取。

Row group級別:

進一步避免讀取不必要的資料,在邏輯上將一個column的index分割成多個index組(預設為10000,可設定)。以這些index記錄為一個組,對資料進行統計。在查詢時可根據組級別的統計資訊過濾掉不必要的資料。

優勢:具有很高的壓縮比,且可切分;由於壓縮比高,在查詢時輸入的資料量小,使用的task減少,所以提升了資料查詢速度和處理效能;每個task只輸出單個檔案,減少了namenode的負載壓力;在ORC檔案中會對每一個欄位建立一個輕量級的索引,如:row group index、bloom filter index等,可以用於where條件過濾;可使用load命令載入,但載入後select * from xx;無法讀取資料;查詢速度比rcfile快;支援複雜的資料型別;

劣勢:無法視覺化展示資料;讀寫時需要消耗額外的CPU資源用於壓縮和解壓縮,但消耗較少;對schema演化支援較差;

5.Parquet

ROW FORMAT SERDE
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
  STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
  OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'

Parquet 最初的設計動機是儲存巢狀式資料,,比如Protocolbuffer,thrift,json等,將這類資料儲存成列式格式,以方便對其高效壓縮和編碼,且使用更少的IO操作取出需要的資料。總的來說Parquet與orc相比的主要優勢是對巢狀結構的支援,orc的多層級巢狀表達複雜底層未採用google dremel類似實現,效能和空間損失較大。

儲存方式:列式儲存

優勢:具有高效壓縮和編碼,是使用時有更少的IO取出所需資料,速度比ORC快;其他方面類似於ORC;

劣勢:不支援update;不支援ACID;不支援視覺化展示資料

 
 ORCParquet
儲存方式列儲存列儲存
巢狀式結構orc的多層級巢狀表達複雜且底層未採用google dremel類似實現,效能和空間損失較大支援比較完美
ACID支援不支援
update操作支援不支援
索引粗粒度索引,block/group/chuck級別統計資訊粗粒度索引,file/stripe/row級別統計資訊,不能精確到列建索引。
查詢效能比parquet稍高比ORC稍低
壓縮

 

6.總結

需要檢視到所儲存的具體資料內容的小型查詢,可以採用預設檔案格式textfile。不需要檢視具體資料的小型查詢時可使用sequencefile檔案格式。當用於巨量資料量的查詢時,可以使用rcfile、ORC、parquet,一般情況下推薦使用ORC,若欄位數較多,不涉及到更新且取部分列查詢場景多的情況下建議使用parquet。

需要通過sqoop+hive與關係型資料庫互動時,import和export的hive表需要是textfile格式。如果需要操作的表不是此儲存格式,需要insert到textfile格式的表中再操作。

一、ORC與Parquet總結對比 1、orc不支援巢狀結構(但可通過複雜資料型別如map<k,v>間接實現),parquet支援巢狀結構 2、orc與hive的相容性強,作為hive的常用儲存格式 3、orc相比parquet的儲存壓縮率較高,如下圖 4、orc匯入資料和資料查詢的的速度比parquet快

 

5.表的行儲存格式(row format)

ROW FORMAT:控制檔案資料和hive表中Row資料的轉換,有DELIMITED和SERDE兩種值,可以將ROW FORMAT看做FileFormat的功能支援或實現,我們設定了FileFormat後,底層資料格式的轉換是依賴SerDe來做的。

DELIMITED:表示使用預設的LazySimpleSerDe類來處理資料,一般用於用分隔符分隔的文字文,預設使用native Serde

SERDE:Serde是 Serializer/Deserializer的簡寫。hive使用Serde進行行物件的序列與反序列化。Hive使用SerDe讀取和寫入行物件。讀取就是hdfs檔案反序列化成物件,寫入就是物件序列化儲存hdfs

read:HDFS files --> InputFileFormat --> <key, value> --> Deserializer --> Row object
write: row object --> Serializer --> <key, value> --> OutputFileFormat --> HDFS files

一般用於比較複雜格式的文字檔案,比如JSON格式行、正規表示式可以匹配出的行,像存取紀錄檔。

 6.表屬性

1.壓縮

1.為什麼要壓縮

可以提高吞吐量和效能,大量減少磁碟儲存空間。同時壓縮也會減少檔案在磁碟間的傳輸及IO消耗,但是壓縮和截壓縮會帶來額外的CPU開銷,但是可以節省更多的IO消耗和記憶體使用。

2.壓縮常見的格式

壓縮方式壓縮後大小壓縮速度是否可切分
GZIP
BZIP2
LZO
Snappy

3.壓縮效能比較

壓縮演演算法 原始檔案大小 壓縮檔案大小 壓縮速度 解壓速度

gzip 8.3GB 1.8GB 17.5MB/S 58MB/S

bzip2 8.3GB 1.1GB 2.4MB/S 9.5MB/S

lzo 8.3GB 2.9GB 49.3MB/S 74.6MB/S

tblproperties ('orc.compress'='snappy')
tblproperties ('parquet.compression'='snappy');

3)開啟MAP輸出階段壓縮 (1)開啟hive中間傳輸資料壓縮功能

hive (default)>set hive.exec.compress.intermediate=true;

(2)開啟mapreduce中map輸出壓縮功能

hive (default)>set mapreduce.map.output.compress=true;

(3)設定mapreduce中map輸出資料的壓縮方式

hive (default)>set mapreduce.map.output.compress.codec=

org.apache.hadoop.io.compress.SnappyCodec;

4)開啟REDUCE輸出階段壓縮,比map端壓縮事兒多 (1)開啟hive最終輸出資料壓縮功能

hive (default)>set hive.exec.compress.output=true;

(2)開啟mapreduce最終輸出資料壓縮

hive (default)>set mapreduce.output.fileoutputformat.compress=true;

(3)設定mapreduce最終資料輸出壓縮方式

hive (default)> set mapreduce.output.fileoutputformat.compress.codec =

org.apache.hadoop.io.compress.SnappyCodec;

(4)設定mapreduce最終資料輸出壓縮為塊壓縮

hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;

在生產環境中,常用的HIVE儲存格式:列式儲存的orc和parquet

HIVE壓縮格式:冷資料-----gzip壓縮(壓縮比高,壓縮解壓縮速度高,不可切割);

非冷資料------lzo(可切割)和snappy(不可切割)

LZO支援切片,Snappy不支援切片。 ORC和Parquet都是列式儲存。 ORC和Parquet 兩種儲存格式都是不能直接讀取的,一般與壓縮一起使用,可大大節省磁碟空間。 選擇:ORC檔案支援Snappy壓縮,但不支援lzo壓縮,所以在實際生產中,使用Parquet儲存 + lzo壓縮的方式更為常見,這種情況下可以避免由於讀取不可分割大檔案引發的資料傾斜。 但是,如果資料量並不大(預測不會有超大檔案,若干G以上)的情況下,使用ORC儲存,snappy壓縮的效率還是非常高的。

ORC支援三種壓縮:ZLIB,SNAPPY,NONE。最後一種就是不壓縮,orc預設採用的是ZLIB壓縮。

Parquet支援的壓縮:UNCOMPRESSED、 SNAPPY、GZP和LZO,預設UNCOMPRESSED不壓縮

到此這篇關於hive常見表結構的文章就介紹到這了,更多相關hive表結構內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com