1. 程式人生 > >大資料11-Hive執行機制與使用

大資料11-Hive執行機制與使用

hive介紹

hive是基於Hadoop的一個數據倉庫工具,可以將結構化的資料檔案對映為一張資料庫表,並提供簡單的sql查詢功能,可以將sql語句轉換為MapReduce任務進行執行。其優點是學習成本低,可以通過類SQL語句快速實現簡單的MapReduce統計,不必開發專門的MapReduce應用,十分適合資料倉庫的統計分析。

 hive的執行機制

圖示

假設我在hive命令列客戶端使用建立了一個數據庫(database)myhive,接著又在該資料庫中建立了一張表emp。

create database myhive;
use myhive;
create table emp(id int,name string);

那麼hive會將元資料儲存在資料庫中。Hive 中的元資料包括表的名字,表的列和分割槽及其屬性,表的屬性(是否為外部表等),表的資料所在目錄等。
hive是基於hadoop的,所以資料庫和表均表現在hdfs上的目錄,資料資訊當然也是儲存在hdfs上。
對於上面的庫和表來說,會在hdfs上建立/user/hive/warehouse/myhive.db這樣的目錄結構,而表的資訊則可以自己上傳個檔案比如圖中的emp.data到/user/hive/warehouse/myhive.db目錄下。那麼就可以寫sql進行查詢了(注:寫查詢語句寫的是myhive這張表不刪emp.data,如select * from myhive,但是查詢到的是emp.data中的資訊,兩者結合可以理解為傳統資料庫的某張表),而這些元資料資訊都會儲存到外部的資料庫中(如mysql,當然也可以使用內嵌的derby,不推薦使用derby畢竟是內嵌的不能共享資訊)。
然後我再寫個查詢語句

select id,name from emp where id>2 order by id desc;

那麼是怎麼執行的呢?查詢語句交給hive,hive利用解析器、優化器等(圖中表示Compiler),呼叫mapreduce模板,形成計劃,生成的查詢計劃儲存在 HDFS 中,隨後由Mapreduce程式呼叫,提交給job放在Yarn上執行。

hive與mapreduce關係

hive的資料儲存
1、Hive中所有的資料都儲存在 HDFS 中,沒有專門的資料儲存格式(可支援Text,SequenceFile,ParquetFile,RCFILE等)
2、只需要在建立表的時候告訴 Hive 資料中的列分隔符和行分隔符,Hive 就可以解析資料。
3、Hive 中包含以下資料模型:DB、Table,External Table,Partition,Bucket。
db:在hdfs中表現為${hive.metastore.warehouse.dir}目錄下一個資料夾
table:在hdfs中表現所屬db目錄下一個資料夾
external table:外部表, 與table類似,不過其資料存放位置可以在任意指定路徑
普通表: 刪除表後, hdfs上的檔案都刪了
External外部表刪除後, hdfs上的檔案沒有刪除, 只是把檔案刪除了
partition:在hdfs中表現為table目錄下的子目錄
bucket:桶, 在hdfs中表現為同一個表目錄下根據hash雜湊之後的多個檔案, 會根據不同的檔案把資料放到不同的檔案中

理論總讓人頭昏,下面介紹hive的初步使用上面的自然就明白了。

hive的使用
雖然可以使用hive與shell互動的方式啟動hive

[[email protected] ~]# cd apps/hive/bin
[[email protected] bin]# ll
總用量 32
-rwxr-xr-x. 1 root root 1031 4月  30 2015 beeline
drwxr-xr-x. 3 root root 4096 10月 17 12:38 ext
-rwxr-xr-x. 1 root root 7844 5月   8 2015 hive
-rwxr-xr-x. 1 root root 1900 4月  30 2015 hive-config.sh
-rwxr-xr-x. 1 root root  885 4月  30 2015 hiveserver2
-rwxr-xr-x. 1 root root  832 4月  30 2015 metatool
-rwxr-xr-x. 1 root root  884 4月  30 2015 schematool
[[email protected] bin]# ./hive
hive>

 

但是介面並不好看,而hive也可以釋出為服務(Hive thrift服務),然後可以使用hive自帶的beeline去連線。如下

視窗1,開啟服務

[[email protected] ~]# cd apps/hive/bin
[[email protected] bin]# ll
總用量 32
-rwxr-xr-x. 1 root root 1031 4月  30 2015 beeline
drwxr-xr-x. 3 root root 4096 10月 17 12:38 ext
-rwxr-xr-x. 1 root root 7844 5月   8 2015 hive
-rwxr-xr-x. 1 root root 1900 4月  30 2015 hive-config.sh
-rwxr-xr-x. 1 root root  885 4月  30 2015 hiveserver2
-rwxr-xr-x. 1 root root  832 4月  30 2015 metatool
-rwxr-xr-x. 1 root root  884 4月  30 2015 schematool
[[email protected] bin]# ./hiveserver2

視窗2,作為客戶端連線

[[email protected] bin]# ./beeline 
Beeline version 1.2.1 by Apache Hive
beeline> [[email protected] bin]# 
[[email protected] bin]# ./beeline 
Beeline version 1.2.1 by Apache Hive
beeline> !connect jdbc:hive2://localhost:10000
Connecting to jdbc:hive2://localhost:10000
Enter username for jdbc:hive2://localhost:10000: root
Enter password for jdbc:hive2://localhost:10000: ******
Connected to: Apache Hive (version 1.2.1)
Driver: Hive JDBC (version 1.2.1)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://localhost:10000>

可能出現錯誤

Error: Failed to open new session: java.lang.RuntimeException: java.lang.RuntimeException: org.apache.hadoop.security.AccessControlException: Permission denied: user=root, access=EXECUTE, inode="/tmp":hadoop3:supergroup:drwx------

./hadoop dfs -chmod -R 777 /tmp

1、檢視資料庫

0: jdbc:hive2://localhost:10000> show databases;
+----------------+--+
| database_name  |
+----------------+--+
| default        |
+----------------+--+
1 row selected (1.456 seconds)

2、建立並使用資料庫,查看錶

0: jdbc:hive2://localhost:10000> create database myhive;
No rows affected (0.576 seconds)
0: jdbc:hive2://localhost:10000> show databases;
+----------------+--+
| database_name  |
+----------------+--+
| default        |
| myhive         |
+----------------+--+
0: jdbc:hive2://localhost:10000> use myhive;
No rows affected (0.265 seconds)
0: jdbc:hive2://localhost:10000> show tables;
+-----------+--+
| tab_name  |
+-----------+--+
+-----------+--+

3、查看錶資訊

結果肯定都是null,因為建立表的時候根本沒指定根據”,”來切分,而檔案中的欄位分隔用了逗號。那麼刪除該表,重新上傳檔案,重新建表語句如下

0: jdbc:hive2://localhost:10000> drop table emp;
No rows affected (1.122 seconds)
0: jdbc:hive2://localhost:10000> show tables;
+-----------+--+
| tab_name  |
+-----------+--+
+-----------+--+
0: jdbc:hive2://localhost:10000> create table emp(id int,name string)
0: jdbc:hive2://localhost:10000> row format delimited
0: jdbc:hive2://localhost:10000> fields terminated by ',';
No rows affected (0.265 seconds)
0: jdbc:hive2://localhost:10000> 

[[email protected] ~]# hadoop fs -put sz.data /user/hive/warehouse/myhive.db/emp
0: jdbc:hive2://localhost:10000> select * from emp;
+---------+-----------+--+
| emp.id  | emp.name  |
+---------+-----------+--+
| 1       | zhangsan  |
| 2       | lisi      |
| 3       | wangwu    |
| 4       | furong    |
| 5       | fengjie   |
+---------+-----------+--+


6、條件查詢

0: jdbc:hive2://localhost:10000> select id,name from emp where id>2 order by id desc;
INFO  : Number of reduce tasks determined at compile time: 1
INFO  : In order to change the average load for a reducer (in bytes):
INFO  :   set hive.exec.reducers.bytes.per.reducer=<number>
INFO  : In order to limit the maximum number of reducers:
INFO  :   set hive.exec.reducers.max=<number>
INFO  : In order to set a constant number of reducers:
INFO  :   set mapreduce.job.reduces=<number>
INFO  : number of splits:1
INFO  : Submitting tokens for job: job_1508216103995_0004
INFO  : The url to track the job: http://mini1:8088/proxy/application_1508216103995_0004/
INFO  : Starting Job = job_1508216103995_0004, Tracking URL = http://mini1:8088/proxy/application_1508216103995_0004/
INFO  : Kill Command = /root/apps/hadoop-2.6.4/bin/hadoop job  -kill job_1508216103995_0004
INFO  : Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
INFO  : 2017-10-18 00:35:39,865 Stage-1 map = 0%,  reduce = 0%
INFO  : 2017-10-18 00:35:46,275 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.33 sec
INFO  : 2017-10-18 00:35:51,487 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 2.34 sec
INFO  : MapReduce Total cumulative CPU time: 2 seconds 340 msec
INFO  : Ended Job = job_1508216103995_0004
+-----+----------+--+
| id  |   name   |
+-----+----------+--+
| 5   | fengjie  |
| 4   | furong   |
| 3   | wangwu   |
+-----+----------+--+
3 rows selected (18.96 seconds)

看到這就能明白了,寫的sql最後是被解析為了mapreduce程式放到yarn上來跑的,hive其實是提供了眾多的mapreduce模板。

7、建立外部表

0: jdbc:hive2://localhost:10000> create external table emp2(id int,name string)
0: jdbc:hive2://localhost:10000> row format delimited fields terminated by ','//指定逗號分割
0: jdbc:hive2://localhost:10000> stored as textfile//文字儲存方式
0: jdbc:hive2://localhost:10000> location '/company';
No rows affected (0.101 seconds)//儲存在/company目錄下

8、載入檔案資訊到表中
前面使用了hadoop命令將檔案上傳到了表對應的目錄下,但是也可以在命令列下直接匯入檔案資訊

0: jdbc:hive2://localhost:10000> load data local inpath '/root/sz.data' into table emp2;(也可以用hadoo直接上傳)
INFO  : Loading data to table myhive.emp2 from file:/root/sz.data
INFO  : Table myhive.emp2 stats: [numFiles=0, totalSize=0]
No rows affected (0.414 seconds)
0: jdbc:hive2://localhost:10000> select * from emp2;
+----------+------------+--+
| emp2.id  | emp2.name  |
+----------+------------+--+
| 1        | zhangsan   |
| 2        | lisi       |
| 3        | wangwu     |
| 4        | furong     |
| 5        | fengjie    |
+----------+------------+--+

9、表分割槽,分割槽欄位為school,匯入資料到2個不同的分割槽中

0: jdbc:hive2://localhost:10000> create table stu(id int,name string)
0: jdbc:hive2://localhost:10000> partitioned by(school string)
0: jdbc:hive2://localhost:10000> row format delimited fields terminated by ',';
No rows affected (0.319 seconds)
0: jdbc:hive2://localhost:10000> show tables;
+-----------+--+
| tab_name  |
+-----------+--+
| emp       |
| emp2      |
| stu       |
| t_sz_ext  |
+-----------+--+
0: jdbc:hive2://localhost:10000> load data local inpath '/root/sz.data' into table stu partition(school='scu');
INFO  : Loading data to table myhive.stu partition (school=scu) from file:/root/sz.data
INFO  : Partition myhive.stu{school=scu} stats: [numFiles=1, numRows=0, totalSize=46, rawDataSize=0]
No rows affected (0.607 seconds)
0: jdbc:hive2://localhost:10000> select * from stu;
+---------+-----------+-------------+--+
| stu.id  | stu.name  | stu.school  |
+---------+-----------+-------------+--+
| 1       | zhangsan  | scu         |
| 2       | lisi      | scu         |
| 3       | wangwu    | scu         |
| 4       | furong    | scu         |
| 5       | fengjie   | scu         |
+---------+-----------+-------------+--+
5 rows selected (0.286 seconds)
0: jdbc:hive2://localhost:10000> load data local inpath '/root/sz2.data' into table stu partition(school='hfut');
INFO  : Loading data to table myhive.stu partition (school=hfut) from file:/root/sz2.data
INFO  : Partition myhive.stu{school=hfut} stats: [numFiles=1, numRows=0, totalSize=46, rawDataSize=0]
No rows affected (0.671 seconds)
0: jdbc:hive2://localhost:10000> select * from stu;
+---------+-----------+-------------+--+
| stu.id  | stu.name  | stu.school  |
+---------+-----------+-------------+--+
| 1       | Tom       | hfut        |
| 2       | Jack      | hfut        |
| 3       | Lucy      | hfut        |
| 4       | Kitty     | hfut        |
| 5       | Lucene    | hfut        |
| 6       | Sakura    | hfut        |
| 1       | zhangsan  | scu         |
| 2       | lisi      | scu         |
| 3       | wangwu    | scu         |
| 4       | furong    | scu         |
| 5       | fengjie   | scu         |
+---------+-----------+-------------+--+

注:hive是不遵循三正規化的,別去考慮主鍵了。

10、新增分割槽

0: jdbc:hive2://localhost:10000> alter table stu add partition (school='Tokyo');

為了更直觀,去頁面檢視