Hadoop 源碼編譯支持Snappy壓縮
資源準(zhǔn)備
- CentOS聯(lián)網(wǎng)
配置CentOS能連接外網(wǎng)。Linux虛擬機(jī)ping www.baidu.com 是暢通的
注意:采用root角色編譯,減少文件夾權(quán)限出現(xiàn)問(wèn)題 - jar包準(zhǔn)備(hadoop源碼、JDK8 、maven、protobuf)
(1)hadoop-2.7.2-src.tar.gz
(2)jdk-8u144-linux-x64.tar.gz
(3)snappy-1.1.3.tar.gz
(4)apache-maven-3.0.5-bin.tar.gz
(5)protobuf-2.5.0.tar.gz
jar包安裝
注意:所有操作必須在root用戶下完成
- JDK解壓、配置環(huán)境變量JAVA_HOME和PATH,驗(yàn)證
tar -zxf jdk-8u144-linux-x64.tar.gz -C /opt/module/
vim /etc/profile
在文件末尾追加
#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_144
export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile
java -version驗(yàn)證
- Maven解壓、配置 MAVEN_HOME和PATH
tar -zxvf apache-maven-3.0.5-bin.tar.gz -C /opt/module/
vim /etc/profile
在文件末尾追加
#MAVEN_HOME
export MAVEN_HOME=/opt/module/apache-maven-3.0.5
export PATH=$PATH:$MAVEN_HOME/bin
source /etc/profile
mvn -version驗(yàn)證
編譯源碼
- 準(zhǔn)備編譯環(huán)境
yum install svn autoconf automake libtool cmake ncurses-devel openssl-devel gcc* - 編譯安裝snappy
cd /opt/software/
tar -zxvf snappy-1.1.3.tar.gz -C /opt/module/
cd /opt/module/snappy-1.1.3/
./configure
make
make install
查看snappy庫(kù)文件
ls -lh /usr/local/lib |grep snappy
- 編譯安裝protobuf
cd /opt/software/
tar -zxvf protobuf-2.5.0.tar.gz -C /opt/module/
cd /opt/module/protobuf-2.5.0/
./configure
make
make install
查看protobuf版本 測(cè)試是否安裝成功
protoc --version
- 編譯hadoop native
cd /opt/software/
tar -zxvf hadoop-2.7.2-src.tar.gz
cd /opt/software/hadoop-2.7.2-src/
mvn clean package -DskipTests -Pdist,native -Dtar -Dsnappy.lib=/usr/local/lib -Dbundle.snappy
執(zhí)行成功后,/opt/software/hadoop-2.7.2-src/hadoop-dist/target/hadoop-2.7.2.tar.gz即為新生成的支持snappy壓縮的二進(jìn)制安裝包。
Hadoop壓縮配置
MP支持的壓縮編碼
| 壓縮格式 | 工具 | 算法 | 文件擴(kuò)展名 | 是否可切片 |
|---|---|---|---|---|
| DEFAULT | 無(wú) | DEFAULT | .deflate | 否 |
| Gzip | gzip | DEFAULT | .gz | 否 |
| bzip2 | bzip2 | bzip2 | .bz2 | 是 |
| LZO | lzop | LZO | .lzo | 是 |
| Snappy | 無(wú) | Snappy | .snappy | 否 |
為了支持多種壓縮/解壓縮算法,Hadoop引入了編碼/解碼器,如下表
| 壓縮格式 | 對(duì)應(yīng)的編碼/解碼器 |
|---|---|
| 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 |
http://google.github.io/snappy/
On a single core of a Core i7 processor in 64-bit mode, Snappy compresses at about 250 MB/sec or more and decompresses at about 500 MB/sec or more.
壓縮參數(shù)配置
要在Hadoop中啟用壓縮,可以配置如下參數(shù)(mapred-site.xml、core-site.xml文件中)
| 參數(shù) | 默認(rèn)值 | 階段 | 建議 |
|---|---|---|---|
| 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使用文件擴(kuò)展名判斷是否支持某種編解碼器 |
| mapreduce.map.output.compress | false | mapper輸出 | 這個(gè)參數(shù)設(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輸出 | 這個(gè)參數(shù)設(shè)為true啟用壓縮 |
| mapreduce.output.fileoutputformat.compress.codec | org.apache.hadoop.io.compress. DefaultCodec | reducer輸出 | 使用標(biāo)準(zhǔn)工具或者編解碼器,如gzip和bzip2 |
| mapreduce.output.fileoutputformat.compress.type | RECORD | reducer輸出 | SequenceFile輸出使用的壓縮類型:NONE和BLOCK |
開(kāi)啟Map輸出階段壓縮
開(kāi)啟map輸出階段壓縮可以減少job中map和Reduce task間數(shù)據(jù)傳輸量。具體配置如下
在hive客戶端進(jìn)行如下操作
- 開(kāi)啟hive中間傳輸數(shù)據(jù)壓縮功能
set hive.exec.compress.intermediate=true; - 開(kāi)啟mapreduce中map輸出壓縮功能
set mapreduce.map.output.compress=true; - 設(shè)置mapreduce中map輸出數(shù)據(jù)的壓縮方式
set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec; - 查詢
開(kāi)啟Reduce輸出階段壓縮
當(dāng)Hive將輸出寫(xiě)入到表中時(shí),輸出內(nèi)容同樣可以進(jìn)行壓縮。屬性hive.exec.compress.output控制著這個(gè)功能。用戶可能需要保持默認(rèn)設(shè)置文件中的默認(rèn)值false,這樣默認(rèn)的輸出就是非壓縮的純文本文件了。用戶可以通過(guò)在查詢語(yǔ)句或執(zhí)行腳本中設(shè)置這個(gè)值為true,來(lái)開(kāi)啟輸出結(jié)果壓縮功能
- 開(kāi)啟hive最終輸出數(shù)據(jù)壓縮功能
set hive.exec.compress.output=true; - 開(kāi)啟mapreduce最終輸出數(shù)據(jù)壓縮
set mapreduce.output.fileoutputformat.compress=true; - 設(shè)置mapreduce最終數(shù)據(jù)輸出壓縮方式
set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec; - 設(shè)置mapreduce最終數(shù)據(jù)輸出壓縮為塊壓縮
set mapreduce.output.fileoutputformat.compress.type=BLOCK; - 測(cè)試一下輸出結(jié)果是否是壓縮文件
insert overwrite local directory '/opt/module/datas/distribute-result' select * from emp distribute by deptno sort by empno desc;
文件存儲(chǔ)格式
Hive支持的存儲(chǔ)數(shù)的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET
列式存儲(chǔ)和行式存儲(chǔ)

如上圖所示左邊為邏輯表,右邊第一個(gè)為行式存儲(chǔ),第二個(gè)為列式存儲(chǔ)
- 行存儲(chǔ)的特點(diǎn)
查詢滿足條件的一整行數(shù)據(jù)的時(shí)候,列存儲(chǔ)則需要去每個(gè)聚集的字段找到對(duì)應(yīng)的每個(gè)列的值,行存儲(chǔ)只需要找到其中一個(gè)值,其余的值都在相鄰地方,所以此時(shí)行存儲(chǔ)查詢的速度更快 - 列存儲(chǔ)的特點(diǎn)
因?yàn)槊總€(gè)字段的數(shù)據(jù)聚集存儲(chǔ),在查詢只需要少數(shù)幾個(gè)字段的時(shí)候,能大大減少讀取的數(shù)據(jù)量;每個(gè)字段的數(shù)據(jù)類型一定是相同的,列式存儲(chǔ)可以針對(duì)性的設(shè)計(jì)更好的設(shè)計(jì)壓縮算法
TEXTFILE和SEQUENCEFILE的存儲(chǔ)格式都是基于行存儲(chǔ)的;
ORC和PARQUET是基于列式存儲(chǔ)的
TextFile格式
默認(rèn)格式,數(shù)據(jù)不做壓縮,磁盤(pán)開(kāi)銷大,數(shù)據(jù)解析開(kāi)銷大??山Y(jié)合Gzip、Bzip2使用,但使用Gzip這種方式,hive不會(huì)對(duì)數(shù)據(jù)進(jìn)行切分,從而無(wú)法對(duì)數(shù)據(jù)進(jìn)行并行操作。
Orc格式
Orc (Optimized Row Columnar)是Hive 0.11版里引入的新的存儲(chǔ)格式

如上圖所示可以看到每個(gè)Orc文件由1個(gè)或多個(gè)stripe組成,每個(gè)stripe250MB大小,這個(gè)Stripe實(shí)際相當(dāng)于RowGroup概念,不過(guò)大小由4MB->250MB,這樣應(yīng)該能提升順序讀的吞吐率。每個(gè)Stripe里有三部分組成,分別是Index Data,Row Data,Stripe Footer
- Index Data,一個(gè)輕量級(jí)的index,默認(rèn)是每隔1W行做一個(gè)索引。這里做的索引應(yīng)該只是記錄某行的各字段在Row Data中的offset。
- Row Data,存的是具體的數(shù)據(jù),先取部分行,然后對(duì)這些行按列進(jìn)行存儲(chǔ)。對(duì)每個(gè)列進(jìn)行了編碼,分成多個(gè)Stream來(lái)存儲(chǔ)。
- Stripe Footer,存的是各個(gè)Stream的類型,長(zhǎng)度等信息。
每個(gè)文件有一個(gè)File Footer,這里面存的是每個(gè)Stripe的行數(shù),每個(gè)Column的數(shù)據(jù)類型信息等;每個(gè)文件的尾部是一個(gè)PostScript,這里面記錄了整個(gè)文件的壓縮類型以及FileFooter的長(zhǎng)度信息等。在讀取文件時(shí),會(huì)seek到文件尾部讀PostScript,從里面解析到File Footer長(zhǎng)度,再讀FileFooter,從里面解析到各個(gè)Stripe信息,再讀各個(gè)Stripe,即從后往前讀
Parquet格式
Parquet是面向分析型業(yè)務(wù)的列式存儲(chǔ)格式,由Twitter和Cloudera合作開(kāi)發(fā),2015年5月從Apache的孵化器里畢業(yè)成為Apache頂級(jí)項(xiàng)目。
Parquet文件是以二進(jìn)制方式存儲(chǔ)的,所以是不可以直接讀取的,文件中包括該文件的數(shù)據(jù)和元數(shù)據(jù),因此Parquet格式文件是自解析的。
通常情況下,在存儲(chǔ)Parquet數(shù)據(jù)的時(shí)候會(huì)按照Block大小設(shè)置行組的大小,由于一般情況下每一個(gè)Mapper任務(wù)處理數(shù)據(jù)的最小單位是一個(gè)Block,這樣可以把每一個(gè)行組由一個(gè)Mapper任務(wù)處理,增大任務(wù)執(zhí)行并行度。Parquet文件的格式如下圖所示

上圖展示了一個(gè)Parquet文件的內(nèi)容,一個(gè)文件中可以存儲(chǔ)多個(gè)行組,文件的首位都是該文件的Magic Code,用于校驗(yàn)它是否是一個(gè)Parquet文件,F(xiàn)ooter length記錄了文件元數(shù)據(jù)的大小,通過(guò)該值和文件長(zhǎng)度可以計(jì)算出元數(shù)據(jù)的偏移量,文件的元數(shù)據(jù)中包括每一個(gè)行組的元數(shù)據(jù)信息和該文件存儲(chǔ)數(shù)據(jù)的Schema信息。除了文件中每一個(gè)行組的元數(shù)據(jù),每一頁(yè)的開(kāi)始都會(huì)存儲(chǔ)該頁(yè)的元數(shù)據(jù),在Parquet中,有三種類型的頁(yè):數(shù)據(jù)頁(yè)、字典頁(yè)和索引頁(yè)。數(shù)據(jù)頁(yè)用于存儲(chǔ)當(dāng)前行組中該列的值,字典頁(yè)存儲(chǔ)該列值的編碼字典,每一個(gè)列塊中最多包含一個(gè)字典頁(yè),索引頁(yè)用來(lái)存儲(chǔ)當(dāng)前行組下該列的索引,目前Parquet中還不支持索引頁(yè)
主流文件存儲(chǔ)格式對(duì)比實(shí)驗(yàn)
從存儲(chǔ)文件的壓縮比和查詢速度兩個(gè)角度對(duì)比
存儲(chǔ)文件的壓縮比
測(cè)試數(shù)據(jù)

- TextFile
-- 創(chuàng)建表,存儲(chǔ)數(shù)據(jù)格式為T(mén)EXTFILE
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 ;
-- 向表中加載數(shù)據(jù)
load data local inpath '/opt/module/datas/log.data' into table log_text ;
-- 查看表中數(shù)據(jù)大小
dfs -du -h /user/hive/warehouse/test.db/log_text;

- ORC
-- 創(chuàng)建表,存儲(chǔ)數(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 ;
-- 向表中加載數(shù)據(jù)
insert into table log_orc select * from log_text ;
-- 查看表中數(shù)據(jù)大小
dfs -du -h /user/hive/warehouse/test.db/log_orc/ ;

- Parquet
-- 創(chuàng)建表,存儲(chǔ)數(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 ;
-- 向表中加載數(shù)據(jù)
insert into table log_parquet select * from log_text ;
-- 查看表中數(shù)據(jù)大小
dfs -du -h /user/hive/warehouse/test.db/log_parquet/ ;

存儲(chǔ)文件的壓縮比總結(jié):
ORC > Parquet > textFile
存儲(chǔ)文件的查詢速度測(cè)試
- TextFile
select count(*) from log_text;

- ORC
select count(*) from log_orc;

- Parquet
select count(*) from log_parquet;

存儲(chǔ)文件的查詢速度總結(jié):查詢速度相近
存儲(chǔ)和壓縮結(jié)合
修改hadoop集群具有Snappy壓縮方式
-
查看hadoop checknative命令使用
hadoop checknative使用.png -
查看hadoop的支持的壓縮方式
hadoop checknative使用.png
上圖已支持Snappy壓縮方式,如果不支持,按照如下步驟操作
- 將編譯好的支持Snappy壓縮的hadoop-2.7.2.tar.gz包導(dǎo)入到hadoop100的/opt/software中
- 解壓hadoop-2.7.2.tar.gz到當(dāng)前路徑
-
進(jìn)入到/opt/software/hadoop-2.7.2/lib/native路徑可以看到支持Snappy壓縮的動(dòng)態(tài)鏈接庫(kù)
支持snappy的hadoop.png - 拷貝/opt/software/hadoop-2.7.2/lib/native里面的所有內(nèi)容到開(kāi)發(fā)集群的/opt/module/hadoop-2.7.2/lib/native路徑上
cp ../native/* /opt/module/hadoop-2.7.2/lib/native/ - 分發(fā)集群
xsync native/ - 再次查看hadoop支持的壓縮類型
- 重新啟動(dòng)hadoop集群和hive
測(cè)試存儲(chǔ)和壓縮
官網(wǎng):https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC
ORC存儲(chǔ)方式的壓縮
| Key | Default | Notes |
|---|---|---|
| orc.compress | ZLIB | high level compression (one of NONE, ZLIB, SNAPPY) |
| orc.compress.size | 262,144 | number of bytes in each compression chunk |
| orc.stripe.size | 67,108,864 | number of bytes in each stripe |
| orc.row.index.stride | 10,000 | number of rows between index entries (must be >= 1000) |
| orc.create.index | true | whether to create row indexes |
| orc.bloom.filter.columns | "" | comma separated list of column names for which bloom filter should be created |
| orc.bloom.filter.fpp | 0.05 | false positive probability for bloom filter (must >0.0 and <1.0) |
- 創(chuàng)建一個(gè)非壓縮的的ORC存儲(chǔ)方式
-- 建表語(yǔ)句
create table log_orc_none(
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");
-- 插入數(shù)據(jù)
insert into table log_orc_none select * from log_text ;
-- 查看插入后數(shù)據(jù)
dfs -du -h /user/hive/warehouse/test.db/log_orc_none/ ;

- 創(chuàng)建一個(gè)SNAPPY壓縮的ORC存儲(chǔ)方式
-- 建表語(yǔ)句
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");
-- 插入數(shù)據(jù)
insert into table log_orc_snappy select * from log_text ;
-- 查看插入后數(shù)據(jù)
dfs -du -h /user/hive/warehouse/test.db/log_orc_snappy/ ;

-
上一節(jié)中默認(rèn)創(chuàng)建的ORC存儲(chǔ)方式,導(dǎo)入數(shù)據(jù)后的大小為
log_orc.png
比Snappy壓縮的還小。原因是orc存儲(chǔ)文件默認(rèn)采用ZLIB壓縮。比snappy壓縮的小
- 存儲(chǔ)方式和壓縮總結(jié)
hive表的數(shù)據(jù)存儲(chǔ)格式一般選擇:orc或parquet。壓縮方式一般選擇snappy,lzo



