大資料基礎學習-7.Hive-1.1.0
一、Hive基礎
Hive是一個SQL解析引擎,將SQL語句轉譯成MR Job,然後在Hadoop平臺上執行,達到快速開發的目的。在沒有hive之前,對HDFS上的檔案或HBase中的表進行查詢時,要手工寫一堆MapReduce程式碼,只能由懂MapReduce的程式設計師才能搞定,耗時耗力。為解決這個問題,FaceBook實現並開源Hive,解決海量結構化日誌查詢。
Hive是資料倉儲,和傳統的資料庫有一定的區別。hive中的表是純邏輯表,即表的後設資料。本質就是Hadoop的目錄/檔案,達到了後設資料與資料儲存分離的目的。Hive本身不儲存資料,它完全依賴HDFS和MapReduce。
– Hive的內容是讀多寫少,不支援對資料的改寫和刪除,只能對資料進行批量地匯入匯出。
【讀時模式:hive只有讀的時候才會檢查資料,解析欄位和schema(schema是資料結構的表達)。優點是寫資料非常快。】
【寫時模式:寫的比較慢,它寫的過程中是需要去建立索引,壓縮、資料一致性、欄位檢查等等,但讀的時候會很快。】
二、Hive概念
Hive是基於Hadoop的一個資料倉儲工具,可以將結構化的資料檔案對映成一張表,並提供類SQL查詢功能(HQL),處理的資料儲存在HDFS,用MapReduce實現底層的資料分析,適合離線處理,執行程式執行在YARN。本質是:將HQL轉換成MapReduce程式。下面介紹幾個關鍵元件。
1.使用者介面: Client
使用者介面用來連線hive服務。其中CLI(hive shell)、JDBC/ODBC(java訪問hive)比較常用,而WEBUI(瀏覽器訪問hive)只能做資料查詢,因此使用較少。
1)cli
命令列模式方式最為常用,將在後面詳細介紹。
2)webui
# hive --service hwi #啟動webui服務,通過http://192.168.101.10:9999/hwi可檢視,但是隻能做資料查詢用,不常用
為了使上述命令能夠正常使用,首先進行2個步驟。第一步先在hive-site.xml中新增如下的配置。
<property>
<name>hive.hwi.listen.host</name>
<value>0.0.0.0</value>
</property>
<property>
<name>hive.hwi.listen.port</name>
<value>9999</value>
</property>
<property>
<name>hive.hwi.war.file</name>
<value>lib/hive-hwi-1.1.0.war</value>
</property>
[root@master lib]# cp /usr/local/src/jdk1.8.0_144/lib/tools.jar . #第二步將tools.jar拷貝到hive的lib目錄下,完成上述2步,即可正常使用啟動命令
3)hiveserver
以JDBC/ODBC的程式登入到hive中運算元據,必須選用遠端服務啟動方式。
2.後設資料: Metastore
hive的後設資料包括:表名、表所屬的資料庫(預設是default)、表的擁有者、列/分割槽欄位、表的型別(是否是外部表)、表的資料所在目錄等;預設儲存在自帶的derby資料庫中,推薦使用採用MySQL儲存Metastore。
3.底層架構:Hadoop
使用HDFS儲存表格資料,使用MapReduce進行計算。
4.驅動器: Driver
包含:解析器、編譯器、優化器、執行器。
解析器:將SQL字串轉換成抽象語法樹(AST),對AST進行語法分析,比如表是否存在、欄位是否存在、SQL語義是否有誤(比如select中被判定為聚合的欄位在group by中是否有出現);
編譯器:將AST編譯生成邏輯執行計劃;
優化器:對邏輯執行計劃進行優化;
執行器:把邏輯執行計劃轉換成可以執行的物理計劃。對於Hive來說,就是MR/TEZ/Spark;
【AST(abstract syntax tree): 是原始碼的抽象語法結構的樹狀表示,樹上的每個節點都表示原始碼中的一種結構,之所以說是抽象的,是因為抽象語法樹並不會表示出真實語法出現的每一個細節,比如說,巢狀括號被隱含在樹的結構中,並沒有以節點的形式呈現。抽象語法樹並不依賴於源語言的語法,也就是說語法分析階段所採用的上下文無文文法,因為在寫文法時,經常會對文法進行等價的轉換(消除左遞迴,回溯,二義性等),這樣會給文法分析引入一些多餘的成分,對後續階段造成不利影響,甚至會使合個階段變得混亂。因些,很多編譯器經常要獨立地構造語法分析樹,為前端、後端建立一個清晰的介面。】
5.hive優點
hive操作介面採用類SQL語法,提供快速開發的能力(簡單、容易上手);避免了去寫MapReduce,減少開發人員的學習成本;統一的後設資料管理,可與impala/spark等共享後設資料;易擴充套件(HDFS+MapReduce:可以擴充套件叢集規模;支援自定義函式)等等。
Hive的執行延遲比較高,因此hive常用於資料分析的,對實時性要求不高的場合;Hive優勢在於處理大資料,對於處理小資料沒有優勢,因為Hive的執行延遲比較高。
三、Hive-1.1.0的安裝
1.解壓hive-1.1.0-cdh5.7.0.tar.gz
tar -zxvf hive-1.1.0-cdh5.7.0.tar.gz
2.安裝mysql
將metastore存放在mysql中,能使得多個機器都能訪問metastore,開啟多個hive視窗,如果後設資料在預設的derby中,只能開啟一個視窗。
[root@master ~]# rpm -qa | grep mysql 首先檢視是否安裝了mysql,有的話,如果版本不對,先解除安裝,centos7安裝的是MariaDB,需要替換掉
# wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
# rpm -ivh mysql-community-release-el7-5.noarch.rpm #安裝後mysql將會替換centos7中的MariaDB
# yum install mysql-community-server
# service mysqld restart
初次安裝mysql,root賬戶沒有密碼,可以直接登入。
# mysql -u root
設定密碼
mysql> use mysql; #首先要切換到mysql的資料庫。
mysql> select host,user,password from user;#首先檢視目前的使用者和密碼資訊。
mysql> set password for'root'@'master' =password('123456');#使master能夠登入hive,密碼為123456
mysql> set password for'root'@'localhost' =password('123456');#將本地登入也採用相同的密碼
mysql> exit;
mysql> update user set password=password('123456') where user='root' and host='localhost';也可以採用這條命令進行密碼設定
注:可以讓使用者進行遠端登入,如下設定。
mysql> GRANT ALL PRIVILEGES ON . TO ‘user’@’%’ IDENTIFIED BY ‘password’ WITH GRANT OPTION;
mysql> flush privileges;
mysql> exit;
設定使用者名稱為:user,密碼為:password的賬號可能通過任意一臺機器訪問資料庫。
3.配置檔案
1)hive-site.xml,連線mysql
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://master:3306/hivemetastore?createDatabaseIfNotExist=true</value>#設定hive後設資料的名稱
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>#配置驅動
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>#配置使用者
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>#配置密碼
</property>
</configuration>
將mysql-connector-java-5.1.27-bin.jar拷貝到hive的lib目錄下。
為了在使用hive時,能夠知道當前使用的database是哪個,可以繼續新增配置資訊如下。
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
2)hive-en.sh
HADOOP_HOME=/usr/local/src/hadoop-2.6.0-cdh5.7.0
4.配置系統環境變數
export HIVE_HOME=/usr/local/src/hive-1.1.0-cdh5.7.0
export PATH=$PATH:$HIVE_HOME/bin
5.在hdfs上建立目錄
首先確保HDFS正常執行,之後進行命令。hive的後設資料預設是存在hdfs上。
$ bin/hadoop fs -mkdir /tmp
$ bin/hadoop fs -p -mkdir /user/hive/warehouse
* 修改目錄許可權
$ bin/hadoop fs -chmod g+w /tmp
$ bin/hadoop fs -chmod g+w /user/hive/warehouse
這時候在輸入hive即可啟動hive。同時使用 mysql -uroot -p123456登入資料庫,在檢視databases時,能夠看到一個叫做hivemetastore的後設資料。
6.修改Hive日誌資訊
$ mv hive-log4j.properties.template hive-log4j.properties
修改其中一條:
hive.log.dir=/usr/local/src/hive-1.1.0-cdh5.7.0/logs
四、Hive基礎命令
1.bin/hive
# bin/hive -help 檢視使用命令
# bin/hive --hiveconf<property=value> 可以在未進入hive時,直接進行相應的配置
# bin/hive -e <quoted-query-string> 直接在未進入hive時,進行hive的操作。
例如:bin/hive-e "select * from db_hive.student ;"
# bin/hive -f <filename> ,這個filename就是執行hive命令的指令碼
例如:# touch hivef.sql,加入如下的內容:select* from db_hive.student ;
# bin/hive -f /opt/datas/hivef.sql
# bin/hive -f /opt/datas/hivef.sql > /opt/datas/hivef-res.txt 輸出結果
* bin/hive -i <filename>,與使用者udf相互使用
進入hive命令列模式下:
hive(default)> dfs -ls / ; 在hive cli命令視窗中如何檢視hdfs檔案系統
hive(default)> !ls /opt/datas;在hive cli命令視窗中如何檢視本地檔案系統
hive > set ;檢視當前所有的配置資訊
hive (db_hive)> set system:user.name ;檢視某個屬性的配置
hive (db_hive)> set system:user.name=beifeng ;為某個屬性進行配置,此種方式,設定屬性的值,僅僅在當前會話session生效
注:以bin/hive --hiveconf hive.root.logger=INFO,console啟動hive,可以將日誌資訊直接輸出到控制檯
2.資料庫的操作
建立資料庫的幾種寫法:
create database db_hive_01 ;
create database if not exists db_hive_01 ;標準寫法
create database if not exists db_hive_01 location /user/hive/warehouse/db_hive_01.db' ;
# hadoop dfs -ls /user/hive/warehouse,可以看到hdfs上建立了db_hive_01資料庫。
檢視建立的資料庫資訊:
desc database db_hive_01 ;
desc database extended db_hive_01 ;更詳細
刪除資料庫:
drop database db_hive_03 ;
drop database db_hive_03 cascade;級聯刪除
drop database if exists db_hive_03 ;標準寫法
3.表的操作
hive> create table student(id int, name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
hive> load data local inpath '/opt/datas/student.txt' into table db_hive.student;
hive> desc extended student;檢視完整的表資訊
hive> desc formatted student;檢視格式良好的資訊
hive> show functions;檢視hive的操作
hive> desc functions 具體函式名稱;
hive> desc extened functions 函式名稱; 更詳細的操作檢視
alter table dept_like rename to dept_like_rename ;改名
drop table if exists dept_like_rename ; 刪除表
truncate table dept_cats ;清除表dept_cats的資料
4.建立表的幾種方式
方式一:
create table IF NOT EXISTS default.bf_log_20150913( #前面加上default是為了指明表建立在該資料庫下
ip string COMMENT 'remote ip address' ,//引數介紹
user string ,
req_url string COMMENT 'user request url')
COMMENT 'Web Access Logs'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' '
STORED AS TEXTFILE ;
load data local inpath '/opt/datas/bf-log.txt' into tabledefault.bf_log_20150913;
方式二:
create table IF NOT EXISTS table2 as select ip,req_url from table2;
通過方式一建立的表格資訊,來建立新的表格,相當於複製了表格的部分或者全部的資訊,這時候新建立的表就會有資料。
方式三:
create table if not exists default.dept_like like default.dept ;只是建立了結構,並沒有資料,這個表結構和default.dept一樣
5.匯出hive資料
方式一:輸出到本地
insert overwrite local directory '/opt/datas/hive_exp_emp' select * from default.emp ;
在本地目錄/opt/datas/下會建立一個hive_exp_emp資料夾,資料夾下存有匯出的資料。還可以按照下面方式指定分割符。
insert overwrite local directory '/opt/datas/hive_exp_emp'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' COLLECTION ITEMSTERMINATED BY '\n'
select * from default.emp ;修改輸出格式
方式二:採用-e方式
bin/hive -e "select * from default.emp ;" >/opt/datas/exp_res.txt
方式三:輸出到hdfs系統
insert overwrite directory '/user/hive/hive_exp_emp' select* from default.emp; 放在檔案系統上
五、Hive表的管理
hive表的本質就是Hadoop的目錄/檔案,實際的資料儲存在hdfs上,hive只是操作這些資料。
1.外部表
管理表(內部表),刪除表時,會刪除表資料以及後設資料,不特別指定時,預設都是內部表。
託管表(外部表),用的多,刪除時候,只會刪除後設資料,不會刪除表資料。
dfs -put /opt/emp.txt /user/hive/warehouse/emp_ext2 #首先將一個日誌檔案上傳到dfs系統中emp_ext2目錄下
create EXTERNAL table IF NOTEXISTS default.emp_ext2(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' location'/user/hive/warehouse/emp_ext2';必須要指定路徑,否則載入不了資料
這時候建立的default.emp_ext2會自動載入剛剛上傳的emp_ext2表資料。如果在/user/hive/warehouse/emp_ext2這個路徑下面,上傳了多個日誌檔案,那麼建立的emp_ext2表會將這些資料全部載入,不論格式是否正確(錯誤的格式在表中會顯示為null)。
需要注意的是,如果在該目錄下也建立了一個管理表,管理表也可以讀取到該目錄下的資料檔案,管理表刪除了將會把資料也刪除掉,導致外部表也讀取不到資料。外部表會顯示空。
2.分割槽表
在Hive 中,表中的一個 Partition 對應表下的一個目錄,所有的 Partition 的資料都儲存在對應的目錄中。
– 例如:pvs 表中包含 ds 和 city 兩個 Partition,則
– 對應於 ds = 20090801,ctry = US 的 HDFS 子目錄為:/wh/pvs/ds=20090801/ctry=US;
– 對應於 ds = 20090801,ctry = CA 的 HDFS 子目錄為;/wh/pvs/ds=20090801/ctry=CA
partition將資料按照一定的規格和條件進行管理,目的是為了輔助查詢,縮小查詢範圍,加快資料的檢索速度,是個非常重要的概念。
create EXTERNAL table IF NOT EXISTS default.emp_partition(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)partitioned by (month string,day string) #這裡要注意分割槽的欄位在建立表中並不存在,但是用desc檢視錶結構,可以看到多了分割槽欄位
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;
hive (default)> desc emp_partition;
OK
col_name data_type comment
empno int
ename string
job string
mgr int
hiredate string
sal double
comm double
deptno int
month string
day string
# Partition Information
# col_name data_type comment
month string
day string
load data local inpath '/opt/datas/emp.txt' into table default.emp_partition partition(month='201509',day='13') ;載入資料,必須要指明分割槽,這個時候在hdfs上就可以看到相應的資料夾。
select * from emp_partition where month = '201509' and day ='13' ;查詢的時候也必須指明具體查的是哪個分割槽。
3.分割槽表注意問題
create table IF NOT EXISTS default.dept_part(
deptno int,
dname string,
loc string
)partitioned by (day string)
ROW FORMAT DELIMITED FIELDSTERMINATED BY '\t';
dfs -mkdir -p/user/hive/warehouse/dept_part/day=20150913 ;
dfs -put /opt/datas/dept.txt /user/hive/warehouse/dept_part/day=20150913 ;
建立表時,並沒有指明該表時分割槽表,如果通過手動方式建立分割槽,hive的後設資料並不知道有這個分割槽的存在,所以該表格只是普通的表格,如果要將該表格轉換為分割槽表,需要進行修復操作。
hive (default)>msck repair table dept_part ;
hive (default)>alter table dept_part add partition(day='20150913');
show partitions dept_part ;查詢分割槽的狀態
4.bucket桶表
Bucket類似於分割槽表,如果想存完整的資料又不想突破一張表的一個能力範圍,可以把一張表拆分成多個表,這個通常叫分庫。
主要目的是為了優化查詢。例如兩個大表都是通過userid來分桶,當做join的時候(自動啟用map端的map-side join),只要命中了第一張表的分桶ID,那麼就可以直接定位到第二張表分桶的ID,提高查詢的速度。第二個優點就是方便取樣。
hive中table可以拆分成partition,partition可以通過‘CLUSTERED BY’進一步分成bucket,bucket中的資料可以通過‘SORT BY’排序。
'set hive.enforce.bucketing = true' 首先開啟桶表功能
create external table rating_table_b
(userId INT,
movieId STRING,
rating STRING
)
clustered by (userId) into 32 buckets;
查詢表的結構:
desc formatted rating_table_b;
灌入輸入:
set hive.enforce.bucketing = true;
from rating_table
insert overwrite table rating_table_b
select userid, movieid, rating; #在表格的目錄下,將會自動生成32個桶表
• 檢視sampling資料:
– hive> select * from student tablesample(bucket 1 out of 2 on id);
– table sample是抽樣語句,語法:TABLESAMPLE( BUCKET x OUT OF y )
– y必須是table總bucket數的倍數或者因子。
hive根據y的大小,決定抽樣的比例。例如,table總共分了64份,當y=32時,抽取(64/32=)2個bucket的資料,當y=128時,抽取(64/128=)1/2個bucket的資料。 x表示從哪個bucket開始抽取。例如,table總bucket數為32,tablesample(bucket 3 out of 16),表示總共抽取(32/16=)2個bucket的資料,分別為第3個bucket和第(3+16=)19個bucket的資料。
5.複合型別
• 資料型別
– 原生型別:TINYINT、SMALLINT、INT、BIGINT、BOOLEAN、FLOAT、DOUBLE、STRING、BINARY(Hive 0.8.0以上才可用)、TIMESTAMP(Hive 0.8.0以上才可用)
– 複合型別:Arrays:ARRAY<data_type>、Maps:MAP<primitive_type, data_type>、Structs:STRUCT<col_name: data_type[COMMENT col_comment],……>、Union:UNIONTYPE<data_type, data_type,……>
例如:select name ,score[‘數學’],就可以查詢到數學成績
INSERT OVERWRITE TABLE pv_users
SELECT pv.pageid, u.age
FROM page_view pv
JOIN user u ON (pv.userid = u.userid);
6.transform
支援多語言,實現類似UDF功能。
1) 欄位拼接
第1種方法:建立AWK指令碼:
]# cat transform.awk
{
print $1"_"$2
}
hive> add file /root/hive_test_3/transform_test/transform.awk; #新增指令碼
執行拼接功能:
select transform(movieid, title) using "awk -f transform.awk" as (uuu) from movie_table;
第2種方法:建立Python指令碼:
]# cat transform.py
import sys
for line in sys.stdin:
ss = line.strip().split('\t')
print '_'.join([ss[0].strip(), ss[1].strip()])
hive> add file/root/hive_test_3/transform_test/transform.py;
執行拼接功能:
hive> select transform(movieid, title)using "python transform.py" as (uuu) from movie_table;
2) wordcount
首先建立文章表,灌入整篇文章:
hive> CREATE TABLE docs(line STRING);
hive> LOAD DATA INPATH '/The_Man_of_Property.txt' OVERWRITE INTO TABLE docs; #先把檔案放入hdfs
開發mapper程式碼:
]# cat mapper.py
import sys
for line in sys.stdin:
ss = line.strip().split(' ')
for word in ss:
print '%s\t1' % (word)
hive> add file/root/hive_test_3/transform_wc/mapper.py;
測試map功能,輸出應該是“單詞+1”格式:
select transform(line) using "python mapper.py" as word,count from docs cluster by word;
開發reduce:
]# cat red.py
import sys
last_key = None
last_count = 0
for line in sys.stdin:
ss = line.strip().split('\t')
if len(ss) != 2:
continue
key = ss[0].strip()
count = ss[1].strip()
if last_key and last_key != key:
print '%s\t%d' % (last_key, last_count)
last_key = key
last_count = int(count)
else:
last_key = key
last_count += int(count)
hive> add file/root/hive_test_3/transform_wc/red.py;
執行map和reduce功能:
select
transform(wc.word, wc.count) using "python red.py" as w, c
from
(select transform(line) using "python mapper.py" as word,count from docs cluster by word) wc;
把wordcount結果儲存起來,建立一張表:
CREATE TABLE word_count(word STRING, countINT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
再次執行map和reduce功能:
insert overwrite table word_count
select
transform(wc.word, wc.count) using"python red.py" as w, c
from
(select transform(line) using "pythonmapper.py" as word,count from docs cluster by word) wc;
查詢確認結果:
hive> select * from word_count order by count desc limit 10;
7.hive整合hbase
首先確保hbase正常啟動。
進入hbase shell終端,建立Hbase表:
hbase shell
create 'classes','user'
插入資料:
put 'classes','001','user:name','jack'
put 'classes','001','user:age','20'
put 'classes','002','user:name','liza'
put 'classes','002','user:age','18'
建立Hive表:
]# cat create_hive_hbase.sql
create external table classes(id int,name string,age int)
STORED BY'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES("hbase.columns.mapping" = ":key,user:name,user:age")
TBLPROPERTIES("hbase.table.name"= "classes");
檢查表結構:
hive> desc formatted classes;
檢查資料:
select * from classes;
刪除hbase某條記錄:
hbase(main):022:0> delete "classes", '001', 'user:name' #再次檢查hive中表格,會發現相應的欄位變成null
六、資料壓縮
資料壓縮可以減小本地磁碟儲存空間和儲存到本地所用時間,即IO,同時減少網路IO傳輸壓力。主要的壓縮有以下幾種方式。
1.snappy
要採用snappy壓縮的話,要編譯Hadoop原始碼
1) 安裝sanppy,解壓即可(已經編譯過)
2) 編譯haodop 2.x原始碼
mvn package-Pdist,native -DskipTests -Dtar -Drequire.snappy
編譯好之後會出現
/opt/modules/hadoop-2.5.0-src/target/hadoop-2.5.0/lib/native
3)進入到2.5.0-native-snappy,這是已經編譯好的檔案
4)將裡面的檔案全部拷貝到hadoop的lib/native下
5)檢查一下是否支援壓縮
$ bin/hadoop checknative
15/08/31 23:10:16 INFO bzip2.Bzip2Factory: Successfully loaded &initialized native-bzip2 library system-native
15/08/31 23:10:16 INFO zlib.ZlibFactory: Successfully loaded &initialized native-zlib library
Native library checking:
hadoop: true /opt/modules/hadoop-2.5.0/lib/native/libhadoop.so
zlib: true /lib64/libz.so.1
snappy: true /opt/modules/hadoop-2.5.0/lib/native/libsnappy.so.1不替換的話,是false
lz4: true revision:99
bzip2: true /lib64/libbz2.so.1
2.MapReduce資料壓縮
6)進行測試,對比壓縮前後
bin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jarwordcount /user/beifeng/mapreduce/wordcount/input /user/beifeng/mapreduce/wordcount/output
bin/yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.5.0.jarwordcount -Dmapreduce.map.output.compress=true-Dmapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec/user/beifeng/mapreduce/wordcount/input/user/beifeng/mapreduce/wordcount/output22
進入8088埠,進入history的configuration,可以看到設定的引數。
3.hive資料壓縮
在hive中設定也是如此:
set -Dmapreduce.map.output.compress=true
set -Dmapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec
七、檔案儲存的格式
hive有如下幾種檔案儲存方式。常用的是ORC和PARQUET。
| SEQUENCEFILE序列化
|TEXTFILE -- (Default, depending on hive.default.fileformatconfiguration)
|RCFILE -- (Note: Available in Hive 0.6.0 andlater)
|ORC -- (Note: Available in Hive0.11.0 and later)
|PARQUET -- (Note: Available in Hive 0.13.0 and later) 列式儲存
|AVRO -- (Note: Available in Hive0.14.0 and later)
|INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
1.textfile
create tablepage_views(
track_timestring,
url string,
session_idstring,
referer string,
ip string,
end_user_idstring,
city_id string
)
ROW FORMATDELIMITED FIELDS TERMINATED BY '\t'
STORED ASTEXTFILE ;
load data localinpath '/opt/datas/page_views.data' into table page_views ;
dfs -du -h /user/hive/warehouse/page_views/ ;
18.1M /user/hive/warehouse/page_views/page_views.data
2.orc
create tablepage_views_orc(
track_timestring,
url string,
session_idstring,
referer string,
ip string,
end_user_idstring,
city_id string
)
ROW FORMATDELIMITED FIELDS TERMINATED BY '\t'
STORED AS orc ;
insertinto table page_views_orc select * from page_views ;企業中生成的方法
dfs -du -h/user/hive/warehouse/page_views_orc/ ;
2.6M /user/hive/warehouse/page_views_orc/000000_0
3.parquet
create tablepage_views_parquet(
track_timestring,
url string,
session_idstring,
referer string,
ip string,
end_user_idstring,
city_id string
)
ROW FORMATDELIMITED FIELDS TERMINATED BY '\t'
STORED AS PARQUET;
insert into tablepage_views_parquet select * from page_views ;
dfs -du -h/user/hive/warehouse/page_views_parquet/ ;
13.1M /user/hive/warehouse/page_views_parquet/000000_0
例子:採用snappy壓縮
create tablepage_views_orc_snappy(
track_timestring,
url string,
session_idstring,
referer string,
ip string,
end_user_idstring,
city_id string
)
ROW FORMATDELIMITED FIELDS TERMINATED BY '\t'
STORED AS orc tblproperties("orc.compress"="SNAPPY");
insert into tablepage_views_orc_snappy select * from page_views ;
dfs -du -h/user/hive/warehouse/page_views_orc_snappy/ ;有3M多,是正常的,因為預設的bzip壓縮是空間最小的
八、UDF、UDAF、UDTF
UDF、UDAF、UDTF只能用java程式碼編寫,根據具體的業務不同編寫不同的程式碼,以下是UDF的例子,講解怎麼給hive配置自己編寫的函式,具體的內容不展開。
1.配置下pom.xml
<!-- Hive Client -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>${hive.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>${hive.version}</version>
</dependency>
2.配置函式
add jar /opt/datas/hiveudf.jar ;
create temporary function my_lower as "hive.udf.LowerUDF" ;
select ename, my_lower(ename) lowername from emp limit 5 ;
或者
CREATE FUNCTION self_lower AS 'hive.udf.LowerUDF'USING JAR 'hdfs://master:8020/user/hive/jars/hiveudf.jar'; jar包必須在檔案系統上
select ename, self_lower(ename) lowername from emp limit 5 ;
九、Hive優化
hive本質是MapReduce,所以很多情況下,hive優化就是針對MapReduce進行。
1.Map的優化:
– 作業會通過input的目錄產生一個或者多個map任務。
– Map越多越好嗎?是不是保證每個map處理接近檔案塊的大小?事實上,map太多則會正價啟動成本,map太少又會較小並行度,所以必須合理取值。
– 如何合併小檔案,減少map數?
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
sethive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
– 如何適當的增加map數?
set mapred.map.tasks=10; 事實上,影響比較小
– Map端聚合hive.map.aggr=true。Mr中的Combiners,提前將結果聚合。
2.Reduce的優化:
– hive.exec.reducers.bytes.per.reducer;reduce任務處理的資料量
reduce的個數= InputFileSize / bytesper reducer
– 調整reduce的個數:
• 設定reduce處理的資料量,設定多少就是多少
setmapred.reduce.tasks=10
select pt,count(1)
from popt_tbaccountcopy_mes
where pt = '2012-07-04' group by pt;
寫成如下,將會導致只有一個reduce執行
select count(1)
from popt_tbaccountcopy_mes
where pt = '2012-07-04';
存在聚合計算的場景:建議開啟group by,防止reduce任務退化成一個。
笛卡爾積:兩個表做join時候,會出現笛卡爾積現象,此時用on替代where。join還有如下的語句優化。
• 一個MR job
SELECT a.val, b.val, c.val
FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (a.key = c.key1)
• 生成多個MR job
SELECT a.val, b.val, c.val
FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key1)
3.分割槽裁剪(partition)
Where中的分割槽條件,會提前生效,不必特意做子查詢,直接Join和Group By。
4.map join
/*+ MAPJOIN(tablelist) */,必須是小表,不要超過1G,或者50萬條記錄,直接放在記憶體中,優化查詢速度。
select /*+ MAPJOIN(A) */ B.userid, A.movieid, B.rating #指定A是小表,不特別指定的話,會按照順序將第一個表放入記憶體中
from movie_table A
join rating_table B
on A.movieid == B.movieid
limit 10;
5.Union all
union all 將兩個表直接合並。先做union all再做join或group by等操作可以有效減少MR過程,儘管是多個Select,最終只有一個mr,資料沒有去重,所以速度較快。
create table a as select * from movie_table limit 10;
create table b as select * from movie_table limit 10;
測試union all:
select count(1)
from (
select c.id
from(
select movieid as id from a
union all
select movieid as id from b
) c
group by c.id) d;
測試union:更耗時
select count(1)
from (
select movieid as id from a
union
select movieid as id from b) c;
6.Multi-insert & multi-group by
– 從一份基礎表中按照不同的維度,一次組合出不同的資料
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1)] select_statement1 group by key1
INSERT OVERWRITE TABLE tablename2 [PARTITION(partcol2=val2 )] select_statement2 group by key2
7.Automatic merge
– 當檔案大小比閾值小時,hive會啟動一個mr進行合併
hive.merge.mapfiles= true 是否和並 Map 輸出檔案,預設為 True
hive.merge.mapredfiles = false 是否合併 Reduce 輸出檔案,預設為 False
hive.merge.size.per.task = 256*1000*1000 合併檔案的大小
8.Multi-Count Distinct
通常產生兩個MR Job,在第一個JOB中,map的輸出結果會隨機分佈到reduce中,每個reduce做部分的聚合操作,並輸出結果,在第二個job中,對於上面預處理的結果按照group by key分佈到reduce中,最終完成聚合操作。自動完成負載均衡,防止資料傾斜。
set hive.groupby.skewindata=true;
9.表連線順序
如果不特別指明,按照JOIN順序中的最後一個表應該儘量是大表,因為JOIN前一階段生成的資料會存在於Reducer的buffer中,通過stream最後面的表,直接從Reducer的buffer中讀取已經緩衝的中間結果資料(這個中間結果資料可能是JOIN順序中,前面表連線的結果的Key,資料量相對較小,記憶體開銷就小),與後面的大表進行連線時,只需要從buffer中讀取快取的Key,與大表中的指定Key進行連線,速度會更快,也可能避免記憶體緩衝區溢位。
SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val
FROM a
JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key1);
a表被視為大表
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM a
JOIN b ON a.key = b.key;
MAPJION會把小表全部讀入記憶體中,在map階段直接拿另外一個表的資料和記憶體中表資料做匹配,由於在map是進行了join操作,省去了reduce執行的效率也會高很多。
使用hint的方式啟發JOIN操作
左連線時,左表中出現的JOIN欄位都保留,右表沒有連線上的都為空。
SELECT a.val, b.val
FROM a
LEFT OUTER JOIN b ON (a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
SELECT a.val, b.val
FROM a
LEFT OUTER JOIN b
ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07')
執行順序是,首先完成2表JOIN,然後再通過WHERE條件進行過濾,這樣在JOIN過程中可能會輸出大量結果,再對這些結果進行過濾,比較耗時。可以進行優化,將WHERE條件放在ON後,在JOIN的過程中,就對不滿足條件的記錄進行了預先過濾。
10.並行實行
同步執行hive的多個階段,hive在執行過程,將一個查詢轉化成一個或者多個階段。某個特定的job可能包含眾多的階段,而這些階段可能並非完全相互依賴的,也就是說可以並行執行的,這樣可能使得整個job的執行時間縮短。
set hive.exec.parallel=true
11.資料傾斜
原因:key分佈不均導致的,人為的建表疏忽,業務資料特點
症狀:任務進度長時間維持在99%(或100%),檢視任務監控頁面,發現只有少量(1個或幾個)reduce子任務未完成。
檢視未完成的子任務,可以看到本地讀寫資料量積累非常大,通常超過10GB可以認定為發生資料傾斜。
傾斜度:平均記錄數超過50w且最大記錄數是超過平均記錄數的4倍。最長時長比平均時長超過4分鐘,且最大時長超過平均時長的2倍。
hive.groupby.skewindata=true #萬能方法
1)資料傾斜-大小表關聯
Hive在進行join時,按照join的key進行分發,而在join左邊的表的資料會首先讀入記憶體,如果左邊表的key相對分散,讀入記憶體的資料會比較小,join任務執行會比較快;而如果左邊的表key比較集中,而這張表的資料量很大,那麼資料傾斜就會比較嚴重,而如果這張表是小表,則還是應該把這張表放在join左邊。
方法:Small_table join big_table。這個可以通過指定大小表來完成。
2)資料傾斜-大大表關聯(通過系統機制)
日誌中有一部分的userid是空或者是0的情況,導致在用user_id進行hash分桶的時候,會將日誌中userid為0或者空的資料分到一起,導致了過大的斜率。
思路:把空值的key變成一個字串加上隨機數,把傾斜的資料分到不同的reduce上,由於null值關聯不上,處理後並不影響最終結果。
方法:過濾語句寫成如下形式。
on case when(x.uid = '-' or x.uid = '0‘ or x.uid is null) then concat('dp_hive_search',rand()) else x.uid end = f.user_id;
3)資料傾斜-大大表關聯(業務削減)
Select * from dw_log t join dw_user t1 on t.user_id=t1.user_id #兩個表都上千萬,跑起來很懸
思路: 當天登陸的使用者其實很少
方法:提前篩選出聚合key
Select /*+MAPJOIN(t12)*/ *
from dw_log t11
join (
select /*+MAPJOIN(t)*/ t1.*
from (
select user_id from dw_log group by user_id 取出使用者id
) t
join dw_user t1
ont.user_id=t1.user_id
) t12 on t11.user_id=t12.user_id
4)資料傾斜-聚合時存在大量特殊值
原因:做countdistinct時,該欄位存在大量值為NULL或空的記錄。
思路:count distinct時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最後結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union
• 方法
select cast(count(distinct (user_id))+1as bigint) as user_cnt
from tab_a
where user_id is not null and user_id<> ''
5)資料傾斜-空間換時間
Select day,count(distinct session_id),count(distinct user_id) from log a group by day;
問題:同一個reduce上進行distinct操作時壓力很大
方法:
select day,
count(case whentype='session' then 1 else null end) as session_cnt,
count(case whentype='user' then 1 else null end) as user_cnt
from (
selectday,session_id,type
from (
select day,session_id,'session'as type
from log
union all #空間換時間
select dayuser_id,'user' as type
from log
)
group by day,session_id,type
) t1
by d
相關文章
- 大資料學習之Linux基礎大資料Linux
- 大資料學習之路——java基礎(二)大資料Java
- 零基礎大資料學習框架大資料框架
- 大資料學習方法,學大資料需要的基礎和路線大資料
- 大資料基礎學習-4.Zookeeper-3.4.5大資料
- 入行IT界,0基礎如何學習大資料?大資料
- 大資料學習記錄,Python基礎(3)大資料Python
- 大資料基礎學習-5.Flume1.6.0大資料
- 大資料基礎學習-6.Kafka2.11大資料Kafka
- 大資料基礎學習-8.Hbase-1.2.0大資料
- 大資料基礎學習-9.Spark2.1.1大資料Spark
- 大資料學習記錄,Python基礎(4)大資料Python
- 學習Java大資料都需要哪些基礎Java大資料
- 學習大資料需要什麼基礎?大資料要學哪些內容?大資料
- 什麼是大資料?零基礎如何學習大資料?(附學習路線)大資料
- 大資料學習:零基礎大資料入門該看哪些書?大資料
- 零基礎大資料學習線路詳解大資料
- 零基礎學習大資料人工智慧,學習路線篇!大資料人工智慧
- 零基礎入門大資料學習,如何才能系統的學好大資料大資料
- 大資料工資這麼高,零基礎可以學習嗎?大資料
- 0基礎學習大資料你需要了解的學習路線和方向大資料
- 大資料學習之路——MySQL基礎(一)——MySQL的基礎知識與常見操作大資料MySql
- 好程式設計師大資料學習路線分享大資料之基礎語法程式設計師大資料
- 大資料分析/機器學習基礎之matplotlib繪圖篇大資料機器學習繪圖
- 零基礎學習大資料為什麼找不到工作?大資料
- 大資料基礎學習-1.CentOS-7.0環境安裝大資料CentOS
- 有基礎學習大資料開發好不好入門大資料
- 大資料需要掌握的數學基礎大資料
- 機器學習基礎-資料降維機器學習
- 轉型進入IT行業,0基礎學習大資料開發需要什麼基礎?行業大資料
- 零基礎學大資料程式設計需要哪些基礎?大資料程式設計
- 0基礎大資料學習路線及各階段學習書籍推薦大資料
- 零基礎的人可以去大資料培訓機構學習大資料開發嗎?大資料
- 大資料——HBase基礎大資料
- 零基礎入門學習大資料可以從事哪些工作?大資料
- 大資料學習者需要了解的10本基礎書籍大資料
- 大資料Java語言基礎培訓學習12條心得感悟大資料Java
- 沒有程式設計基礎的小白可以學習大資料嗎?程式設計大資料