第 9 章:壓縮和存儲
Hive不會強制要求將數(shù)據(jù)轉(zhuǎn)換成特定的格式才能使用。利用Hadoop的InputFormat API可以從不同數(shù)據(jù)源讀取數(shù)據(jù),使用OutputFormat API可以將數(shù)據(jù)寫成不同的格式輸出。
對數(shù)據(jù)進行壓縮雖然會增加額外的CPU開銷,但是會節(jié)約客觀的磁盤空間,并且通過減少內(nèi)存的數(shù)據(jù)量而提高I/O吞吐量會更加提高網(wǎng)絡傳輸性能。
原則上Hadoop的job時I/O密集型的話就可以采用壓縮可以提高性能,如果job是CPU密集型的話,那么使用壓縮可能會降低執(zhí)行性能。
9.1 Hadoop壓縮配置
9.1.1 MR支持的壓縮編碼
壓縮格式 | 算法 | 文件擴展名 | 是否可切分 |
---|---|---|---|
Deflate | Deflate | .deflate | 否 |
Gzip | Deflate | .gz | 否 |
Bzip2 | Bzip2 | .bz2 | 是 |
Lzo | Lzo | .lzo | 是 |
Snappy | Snappy | .snappy | 否 |
為了支持多種壓縮/解壓縮算法,Hadoop引入了編碼/解碼器,如下表所示:
壓縮格式 | 對應的編碼/解碼器 |
---|---|
Deflate | org.apache.hadoop.io.compress.DefaultCodec |
Gzip | org.apache.hadoop.io.compress.GzipCodec |
Bzip2 | org.apache.hadoop.io.compress.BZip2Codec |
Lzo | com.hadoop.compression.lzo.LzopCodec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
為什么需要這么多的壓縮方案呢?
每一個壓縮方案都在壓縮和解壓縮速度和壓縮率間進行權衡。
如下是壓縮性能的比較
壓縮算法 | 原始文件大小 | 壓縮文件大小 | 壓縮速度 | 解壓速度 |
---|---|---|---|---|
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 |
9.1.2 壓縮參數(shù)配置
要在Hadoop中啟用壓縮,可以配置如下參數(shù)(mapred-site.xml文件中):
參數(shù) | 默認值 | 階段 | 建議 |
---|---|---|---|
io.compression.codecs (在core-site.xml中配置) | org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.Lz4Codec | 輸出壓縮 | Hadoop使用文件擴展名判斷是否支持某種編解碼器 |
mapreduce.map.output.compress | false | mapper輸出 | 這個參數(shù)為true啟動壓縮 |
mapreduce.map.output.compress.codec | org.apache.hadoop.io.compress.DefaultCodec | mapper輸出 | 使用LZO、LZ4或snappy編解碼器在此階段壓縮數(shù)據(jù) |
mapreduce.output.fileoutputformat.compress | false | reducer輸出 | 這個參數(shù)設為true啟動壓縮 |
mapreduce.output.fileoutputformat.compress.codec | org.apache.hadoop.io.compress. DefaultCodec | reducer輸出 | 使用標準工具或者編碼器,如gzip和bzip2 |
mapreduce.output.fileoutputformat.compress.type | RECORD | reducer輸出 | SequenceFile輸出使用的壓縮類型:NONE和BLOCK |
9.2 開啟Map輸出階段壓縮
開啟map輸出階段壓縮可以減少job中map和Reduce task間數(shù)據(jù)傳輸量。
1、具體配置如下:
1)開啟hive中間傳輸數(shù)據(jù)壓縮功能
set hive.exec.compress.intermediate =true;
2)開啟mapreduce中map輸出壓縮功能
set mapreduce.map.output.compress=true;
3)設置mapreduce中map輸出數(shù)據(jù)的壓縮方式
set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
4)執(zhí)行查詢語句
select count(ename) name from emp;
5)觀察yarn執(zhí)行的job的map階段日志可看到如下內(nèi)容
9.3 開啟Reduce輸出階段壓縮
當Hive將輸出寫入到表中時可以通過屬性hive.exec.compress.output,對輸出內(nèi)容進行壓縮。當hive.exec.compress.output=false,這樣輸出就是非壓縮的純文本文件了。將hive.exec.compress.output=true,來開啟輸出結(jié)果壓縮功能。
1、設置步驟如下:
1)開啟hive最終輸出數(shù)據(jù)壓縮功能
set hive.exec.compress.output=true;
2)開啟mapreduce最終輸出數(shù)據(jù)壓縮
set mapreduce.output.fileoutputformat.compress=true;
3)設置mapreduce最終數(shù)據(jù)輸出壓縮方式
set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
4)設置mapreduce最終數(shù)據(jù)輸出壓縮為塊壓縮
set mapreduce.output.fileoutputformat.compress.type=BLOCK;
5)測試以下輸出結(jié)果是否為壓縮文件
insert overwrite local directory
'/opt/module/hive/datas/distribute-result' select * from emp distribute by deptno sort by empno desc;
6)查看目錄/opt/module/hive/datas/distribute-result下文件
distribute-result]$ ll
總用量 4
-rw-r--r--. 1 atguigu atguigu 493 10月 21 22:56 000000_0.snappy
9.4 文件存儲格式
Hive支持的存儲數(shù)據(jù)的格式主要有:TEXTFILE、SEQUENCEFILE、ORC、PARQUET。
9.4.1 列式存儲和行式存儲
如圖所示,左邊為邏輯表,右邊第一個是行式存儲,第二個式列式存儲。
9.4.2 TextFile格式
默認格式,數(shù)據(jù)不做壓縮,磁盤開銷大,數(shù)據(jù)解析開銷大。
可結(jié)合Gzip,Bzip2使用,但使用Gzip這種方式,hive不會對數(shù)據(jù)進行切分,從而無法對數(shù)據(jù)進行并行操作。
9.4.3 Orc格式
Orc是Hive 0.11版里引入的新的存儲格式。
如下圖所示可以看到每個Orc文件由1個或多個stripe組成,每個stripe一般為HDFS的塊大小,每一個stripe包含多條記錄,這些記錄按照列進行獨立存儲,對應到Parquet中的row group的概念。每個Stripe里有三部分組成,分別是Index Data, Row Data,Stripe Footer;
1、Index Data:一個輕量級的index,默認是每隔1W行做一個索引。這里做的索引應該只是記錄某行的各字段在Row Data中的offset。
2、Row Data:存的是具體的數(shù)據(jù),先取部分行,然后對這些行按列進行存儲。對每個列進行了編碼,分成多個Stream來存儲。
3、Stripe Footer:存的是各個Stream的類型,長度等信息。每個文件有一個File Footer,這里面存的是每個Stripe的行數(shù),每個Column的數(shù)據(jù)類型信息等;每個文件的尾部是一個PostScript,這里面記錄了整個文件的壓縮類型以及FileFooter的長度信息等。在讀取文件時,會seek到文件尾部讀PostScript,從里面解析到File Footer長度,再讀FileFooter,從里面解析到各個Stripe信息,再讀各個Stripe,即從后往前讀。
9.4.4 Parquet格式
Parquet文件是以二進制方式存儲的,所以是不可以直接讀取的。文件中包括該文件的數(shù)據(jù)和元數(shù)據(jù),因此Parquet格式文件是自解析的。
1、行組(Row Group):每一個行組包含一定的行數(shù),在一個HDFS文件中至少存儲一個行組,類似于orc的stripe的概念。
2、列塊(Column Chunk):在一個行組中每一列保持在一個列塊中,行組中的所有列連續(xù)的存儲在這個行組文件中。一個列塊中的值都是相同類型的,不同列塊可能使用不同的算法進行壓縮。
3、頁(Page):每一個列塊劃分為多個頁,一個頁是最小的編碼的單位,在同一個列塊的不同頁可能使用不同的編碼方式。
通常情況下,在存儲Parquet數(shù)據(jù)的時候會按照Block大小設置行組的大小,由于一般情況下每一個Mapper任務處理數(shù)據(jù)的最小單位是一個Block,這樣可以把每一個行組由一個Mapper任務處理,增大任務執(zhí)行并行度。
上圖展示了一個Parquet文件的內(nèi)容,一個文件中可以存儲多個行組,文件的首位都是該文件的Magic Code,用于校驗它是否是一個Parquet文件,F(xiàn)ooter length記錄了文件元數(shù)據(jù)的大小,通過該值和文件長度可以計算出元數(shù)據(jù)的偏移量,文件的元數(shù)據(jù)中包括每一個行組的元數(shù)據(jù)信息和該文件存儲數(shù)據(jù)的Schema信息。除了文件中每一個行組的元數(shù)據(jù),每一頁的開始都會存儲該頁的元數(shù)據(jù),在Parquet中,有三中類型的頁:數(shù)據(jù)頁、字典頁和索引頁。數(shù)據(jù)頁用于存儲當前行組中該列的值,字典頁存儲該列值的編碼字典,每一個列塊中最多包含一個字典頁,索引頁用來存儲當前行組下該列的索引,目前Parquet中還不支持索引頁。
9.4.5 主流存儲文件格式對比
1、TextFile
1)創(chuàng)建log_text,設置其存儲數(shù)據(jù)格式為TEXTFILE
create table log_text (
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as textfile;
2)向表中加載數(shù)據(jù)
load data local inpath '/opt/module/hive/datas/log.data' into table log_text ;
3)查看表中數(shù)據(jù)大小
dfs -du -h /user/hive/warehouse/log_text;
18.1 M 54.4 M /user/hive/warehouse/log_text/log.data
4)采用TextFile格式存儲,文件大小為18.1M
2、ORC
1)創(chuàng)建表loc_orc,存儲數(shù)據(jù)格式是ORC
create table log_orc(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="NONE"); // 由于ORC格式時自帶壓縮的,這設置orc存儲不使用壓縮
2)向表中插入數(shù)據(jù)
insert into table log_orc select * from log_text ;
3)查看表中數(shù)據(jù)大小
dfs -du -h /user/hive/warehouse/log_orc/ ;
7.7 M 23.1 M /user/hive/warehouse/log_orc/000000_0
4)采用ORC(非壓縮)格式存儲,文件大小為7.7M
3、Parquet
1)創(chuàng)建表log_parquet,設置其存儲數(shù)據(jù)格式為parquet
create table log_parquet(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as parquet ;
2)向表中插入數(shù)據(jù)
insert into table log_parquet select * from log_text ;
3)查看表中數(shù)據(jù)大小
dfs -du -h /user/hive/warehouse/log_parquet/ ;
13.1 M 39.3 M /user/hive/warehouse/log_parquet/000000_0
4)采用Parquet格式存儲,文件大小為13.1M
4、存儲文件的對比總結(jié):
ORC>Parquet>textFile
5、存儲文件的查詢速度測試:
1)TextFile
insert overwrite local directory '/opt/module/hive/data/log_text' select substring(url,1,4) from log_text ;
No rows affected (10.522 seconds)
2)ORC
insert overwrite local directory '/opt/module/hive/data/log_orc' select substring(url,1,4) from log_orc ;
No rows affected (11.495 seconds)
3)Parquet
insert overwrite local directory '/opt/module/hive/data/log_parquet' select substring(url,1,4) from log_parquet ;
No rows affected (11.445 seconds)
存儲文件的查詢速度總結(jié):查詢速度相近
9.5 存儲和壓縮結(jié)合
9.5.1 測試存儲和壓縮
1、創(chuàng)建一個ZLIB壓縮的ORC存儲方式
1)創(chuàng)建表log_orc_zlib表,設置其使用ORC文件格式,并使用ZLIB壓縮
create table log_orc_zlib(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="ZLIB");
2)向表log_orc_zlib插入數(shù)據(jù)
insert into log_orc_zlib select * from log_text;
3)查看插入后數(shù)據(jù)文件大小
dfs -du -h /user/hive/warehouse/log_orc_zlib/ ;
2.8 M 8.3 M /user/hive/warehouse/log_orc_zlib/000000_0
4)采用ORC文件格式,并使用ZLIB壓縮時,文件大小2.8M
2、創(chuàng)建一個SNAPP壓縮的ORC存儲方式
1)創(chuàng)建表log_orc_snappy表,設置其使用ORC文件格式,并使用snappy壓縮
create table log_orc_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="SNAPPY");
2)插入數(shù)據(jù)
insert into log_orc_snappy select * from log_text;
3)查看插入后數(shù)據(jù)
dfs -du -h /user/hive/warehouse/log_orc_snappy/ ;
3.7 M 11.2 M /user/hive/warehouse/log_orc_snappy/000000_1
4)采用ORC文件格式,并使用SNAPPY壓縮時,文件大小3.7M
ZLIB比Snappy壓縮的還小。原因是ZLIB采用的是deflate壓縮算法。比snappy壓縮的壓縮率高。
3、創(chuàng)建一個SNAPPY壓縮的parquet存儲方式
1)創(chuàng)建表log_parquet_snappy,設置其使用Parquet文件格式,并使用SNAPPY壓縮
create table log_parquet_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as parquet
tblproperties("parquet.compression"="SNAPPY");
2)向表log_parquet_snappy插入數(shù)據(jù)
insert into log_parquet_snappy select * from log_text;
3)查看插入后數(shù)據(jù)文章來源:http://www.zghlxwxcb.cn/news/detail-798178.html
dfs -du -h /user/hive/warehouse/log_parquet_snappy / ;
6.4 M 19.2 M /user/hive/warehouse/log_parquet_snappy/000000_0
4)采用Parquet文件格式,并使用SNAPPY壓縮時,文件大小6.4MB
4、存儲方式和壓縮總結(jié)
在實際的項目開發(fā)當中:
1)hive表的數(shù)據(jù)存儲格式一般選擇:orc或parquet
2)壓縮方式一般選擇snappy,lzo文章來源地址http://www.zghlxwxcb.cn/news/detail-798178.html
到了這里,關于大數(shù)據(jù)開發(fā)之Hive(壓縮和存儲)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!