About Hive
- 1) ---Hive概述
- 2) ---Hive的安裝配置
- 3) ---Hive的入門
- 4) ---Hive的元資料庫
- 5) ---Hive的內部表、外部表
- 6) ---Hive的分區表
- 7) ---Hive的分桶表
- 8) ---Hive的內置運算符及內置函數
- 9) ---Hive的語法
- 10)---HiveUDF概述(用戶自定義函數)
- 11)---Hive的JDBC操作(了解)
(1)---Hive概述
1.MapReduce遇到的問題
- 必須會編程
- 必須對MR的底層實現有深入理解
- 開發調試比較麻煩
能不能用一種更加通用的 簡單的方式 來實現對海量數據的處理 -- sql -- 能不能用sql來實現對海量數據的處理 -- hive就是這樣的一個工具
2.Hive的原理
Hive就是在hadoop的基礎上架設了一層sql操作的介面,使我們可以通過類sql的hql來操作hive,由hive將這些hql語句翻譯成mapreduce來處理海量數據。所以,Hive的底層仍然是MapReduce,Hive主要是做一個翻譯的工作。
3.Hive是基於Hadoop的數據倉庫工具
a.資料庫和數據倉庫的比較
b.Hive的特點
- Hive將結構化的數據文件映射為一張資料庫表,並提供完整的sql查詢能力。
- 只能一次寫入多次查詢不支持行級別的增刪改查(hadoop2.0後可以追加)這是受限於底層的hdfs
- 本質上只是在hadoop的基礎上加了一層sql的殼,仍然是一種離線數據分析工具
- 不支持事務的特性
- 通常會通過製造冗餘來提高數據的查詢能力
c.結論
Hive並不是一種資料庫,而是一種基於Hadoop的數據倉庫工具。
4.Hive的優缺點
優點:
學習成本低,只要會sql就能用hive
開發效率高,不需要編程,只需要寫sql
模型簡單,易於理解
缺點:
不支持行級別的增刪改
不支持在線事務處理
本質上仍然是MR的執行,效率不算高
(2)---Hive的安裝配置
1.準備
安裝JDK,配置JAVA_HOME
安裝Hadoop,並配置HADOOP_HOME
2.下載安裝包
訪問Hive官網,下載Hive的安裝包
Apache Hive TM3.安裝
將下載好的hive安裝包上傳到linux中,進行解壓
4.啟動Hive
啟動好Hadoop
進入hive/bin目錄,直接運行hive命令,即可進入hive提示符
(3)---Hive的入門
1.Hive案例
在hive>下執行
show databases;
create databases parkdb;
打開hadoop hdfs的訪問頁面(50070)
可以在hdfs上找到剛剛創建的資料庫
==a.結論1:Hive中的資料庫就是底層HDFS中的一個[庫名.db]文件夾
執行創表操作
會在剛剛的文件夾下創建一個以表名為名字的文件夾
==b.結論2:Hive中的表就是底層HDFS中庫名文件夾下以表名為名字的子文件夾
向表中加入數據
(這裡是本地文件寫入的方式)
load data local inpath /home/software/student.txt into table stu;
當然也可能會出現這樣的數據
沒讀到是因為之前創表的時候聲明了表底層的文件中以tab分隔欄位
所以不是以tab方式分隔的欄位沒有成功獲取
==c.結論3:Hive表中的數據其實就是在HDFS中Hive表對應的文件夾下的文件
查詢一共有幾條數據
select count(*)from stu;
==d.結論4:Hive中的hql會轉換為底層的MR來執行
==e.結論5:hive內置的default庫,對應的就是hdfs中/user/hive/warehouse目錄
(4)---Hive的元資料庫
當你以./bin/hive等多級目錄的方式打開hive時會發現剛才的數據都不見了
why?--》
Hive中除了保存真正的數據以外還要額外保存用來描述庫、表、列的數據,稱為hive的元數據。hive需要將這些元數據存放在另外的關係型資料庫中,默認情況下Hive將這些數據存儲在hive內置的derby的資料庫中。
然而derby存在以下問題:
--1.derby資料庫是一種文件型的資料庫,在進入時會檢查當前目錄下是否有metastore_db文件夾用來存儲資料庫數據,如果有就直接使用,如果沒有就創建,這樣一旦換一個目錄,元數據就找不到了。
--2.derby資料庫是一個單用戶的資料庫,無法支持多用戶同時操作,而hive如果使用derby作為元資料庫,則也只能支持單用戶操作。
綜上所述,Hive安裝完成之後,通常都需要替換元資料庫,目前Hive只支持derby和mysql兩種資料庫,需要將元資料庫替換為mysql,這樣hive所有的元數據都存放在同一個庫里,可以實現資源的共享。
*這裡補充在Linux中安裝Mysql
(刪除原有版本)
因為我之前是用Percona-Server相關工具包下的mysql所以這邊把這些刪了先
#將rpm包上傳到/home/software目錄(也可以是其他目錄)
MySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm
MySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm
#查看之前是否安裝過mysql
rpm -qa | grep -i mysql
#如果安裝過,執行這行代碼,刪除之前安裝過的mysql
rpm -ev --nodeps mysql-libs-5.1.71-1.el6.x86_64(根據版本更改)
查找之前老版本mysql的目錄、並且刪除老版本mysql的文件和庫
(見圖)
find / -name mysql
注意:卸載後/etc/my.cnf不會刪除,需要進行手工刪除
#增加用戶組mysql
groupadd mysql
#增加用戶mysql,加入mysql用戶組
useradd -r -g mysql mysql
#安裝server
rpm -ivh MySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm
#安裝client
rpm -ivh MySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm
====mysql5.6安裝後所在的目錄====================================================================
Directory Contents of Directory
/usr/bin Client programs and scripts
/usr/sbin The mysqld server
/var/lib/mysql Log files, databases
/usr/share/info MySQL manual in Info format
/usr/share/man Unix manual pages
/usr/include/mysql Include (header) files
/usr/lib/mysql Libraries
/usr/share/mysql Miscellaneous support files, including error messages, character set files, sample configuration files, SQL for database installation
/usr/share/sql-bench Benchmarks
==========================================================================================
#修改my.cnf,默認在/usr/my.cnf find / -name my.cnf
vim /usr/my.cnf
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character_set_server=utf8
# basedir = .....
# datadir = .....
# port = .....
# server_id = .....
# socket = .....
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#將mysqld加入系統服務,並隨機啟動
cp /usr/share/mysql/mysql.server /etc/init.d/mysqld
#啟動mysqld
service mysqld start
#獲取mysql安裝時root用戶的隨機密碼
cat /root/.mysql_secret
#必須要修改root用戶的密碼才可以使用mysql,否則只能連接不能操作
mysqladmin -u root -p password root
#連接進入mysql
mysql -u root -p
root
#查看mysql的安裝運行路徑
ps -ef|grep mysql
---修改Hive的元資料庫為mysql
#cp hive-default.xml.template hive-site.xml
--在hive安裝目錄的conf目錄下複製hive-default.xml.template 為hive-site.xml
打開此文件 vim hive-site.xml
刪除configuration標籤原有內容配置如下信息在configuration標籤中
(註:dG刪除游標所在行到最後一行)
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoopx:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>
注意以上配置信息,可根據實際情況進行具體修改
可能會遇到的問題:
1.the specified datastore driver was not found資料庫驅動未找到
將mysql的驅動複製到hive的lib目錄下,
2.Access denied 許可權問題
登錄mysql開啟mysql的當前機器的root用戶訪問許可權
GRANT ALL PRIVILEGES ON *.* TO root@% IDENTIFIED BY root WITH GRANT OPTION;(針對所有機器)
GRANT ALL PRIVILEGES ON *.* TO root@hadoop01 IDENTIFIED BY root WITH GRANT OPTION;(針對hadoop01這台機器)
FLUSH PRIVILEGES;(刷新mysql系統許可權相關表)
3.在hive中創建表格報錯
mysql元資料庫中的hive庫,編碼集為utf8,而hive要求必須是latin1
刪除該元資料庫,手動創建名字為hive,編碼集為latin1的元資料庫
drop database hive;
create database hive charset latin1;
這樣就將元資料庫替換為了mysql
---hive的元資料庫中重要的表
a.DBS
存儲了hive庫相關的信息,包括編號、庫名稱、庫所有者、庫對應在hdfs中的存儲位置
b.TBLS
存儲了hive中表相關的信息,包括表的編號、所屬的庫的編號、表所有者、表名稱、表類型
c.COLUMNS_V2
存儲了hive中表對應列的信息,包括所屬表的編號、列名稱、列類型、列的位置
d.SDS
存儲了hive表對應在HDFS中的存儲位置信息,包括表的編號、存儲位置
(5)---Hive的內部表、外部表
1.內部表
hive默認創建的表為內部表,表的類型為MANAGED_TABLE
2.外部表
在真實開發中,很有可能在hdfs中已經有了數據,希望通過hive直接訪問這些數據作為表內容,
此時可以創建hive表關聯到該位置,管理其中的數據,這就是所謂的外部表
創建方式:在建表時加external
如create external table ... location xxx;
3.區別
內部表:
先有表、後有數據,數據被存儲到hdfs目錄下表對應的文件夾進行管理。
外部表:
先有數據後有表,hive表關聯到該位置管理其中的數據。
在刪除表的過程中,內部表刪除元數據,對應在hdfs中表對應的文件夾及其中的數據也會被刪除。
(測試了一下,在hdfs里刪除表對應的文件夾及其中的數據時,對hive中表內容無影響,向表中新增數據時,hdfs里會再次創建對應文件夾)
外部表刪除時,只會刪除元數據,對應在hdfs中的表對應的文件夾及其中的數據不會被刪除。
(6)---Hive的分區表
利用分區表可以對數據進行分區來提高查詢的效率,在大量數據經常要按照某些特定欄位查詢時可以設計分區表來提高效率。
-創建帶有分區的表:
create table book(id bigint,name string) partitioned by (country string,xing string ...) row format delimited fields terminated by ;
-向表的分區裡面載入數據:
load data local inpath ./book_china.txt into table book partition (country=china,...);
(local是本地打開hive的路徑,不加local是hdfs路徑)
-修改表結構增加分區:
ALTER TABLE book add PARTITION (country=jp,...) location /user/hive/warehouse/...;
Hive分區的原理
分區表就是在表的文件夾下創建對應分區的文件夾,將表中的數據按照分區欄位分放在不同的分區文件夾下,這樣之後按照分區欄位查詢數據時,可以直接找到分區文件夾得到數據,而不用在全部數據中進行過濾,從而提升了查詢的效率。
三條語句執行結果
發現創建多個分區的表,在hdfs中多個分區形成了多層文件夾,在元數據中,這些位置都被加入了SDS。
如果是自己手動在hdfs中的分區裡面創建文件夾,通過hql查表是獲取不到數據的,需要通過hql命令來修改表結構增加分區信息。
比如在book下創建以下目錄
-country=dudu
--xing=dudu
upload以下文件到這個目錄(jp.txt)
通過hql查詢表select * from book;
無法獲取以上內容
通過hql語句:
alter table book add partition(country=dudu,xing=dudu) location /user/hive/warehouse/park.db/book/country=dudu/xing=dudu;
添加分區後再執行select * from book;
就可以查詢到以上信息了
hql對分區的操作語句
---添加分區:
alter table xxx add [if not exists] partition (xxx=xxx,...) ;
---刪除分區:
alter table xxx drop [if exists] partition (xxx=xxx);
(方括弧內的語句可省略)
(7)---Hive的分桶表
Hive中也支持分桶表,分桶表是一種更細粒度的數據分配方式。
一個表既可以分區,也可以分桶。
分桶的主要作用是實現數據的抽樣,方便進行數據測試。
分桶表通過hash分桶演算法,將數據分放在不同的桶(hdfs中的文件)中,方便後續讀取。
Hive中分桶的功能是默認關閉的,需要手動開啟
set hive.enforce.bucketing=true;
Hive的分桶過程是在底層的MR中實現的,所以必須在一個MR過程中分桶才可以實現,通常我們不會直接在原始的表中實現分桶,而是單獨創建一個帶有分桶的測試表,從原始表中向分桶的測試表中導入數據,在導入的過程中,觸發MR操作,實現分桶。
創建分桶表的語法:
create table bucket(id int,name string) clustered by (id) into 2 buckets row format delimated fields terminated by |;
進行數據抽樣的語法:
select * from bucket tablesample(bucket 1 out of 2 on id);
一般步驟:
1)創建原始數據表,導入數據
create table bucket_back(id int,name string) row format delimited fields terminated by |;
load data inpath /file/teachers.txt into table bucket_back;
2)創建帶有分桶的測試表
create table bucket(id int,name string) clustered by(id) into 2 buckets row format delimited fields terminated by |;
3)從原始表中導入數據到分桶表
insert into bucket select * from bucket_back;
從分桶表中查詢數據:
select * from bucket tablesample(bucket 1 out of 2 on id);
(bucket 1 out of 2其實就是將桶分成了兩個,然後取出其中1號桶中的數據)
(將2和1換成其他數字也可嘗試)
無論表是否進行過分桶都不影響tablesample函數執行抽樣的過程,但是如果能夠保證表是經過分桶的且分桶的數量和抽樣的數量相同,則tablesample函數可以直接從表對應的文件夾下獲取物理分割好的桶的數據返回,從而可以具有良好的性能,所以建議如果對海量的數據進行抽樣,最好經過分桶後再抽樣,且保證桶的數量和抽樣的數量相同。
(8)---Hive的內置運算符及內置函數
Hive實現了標準的sql,但在這之外,為了提升hive處理數據的能力,還額外提供了很多內置的函數,這些內置函數非常豐富,且可以直接使用,雖然不屬於sql原生的語法,但大大的增強了hive處理數據的能力,是hive功能的重要組成部分。
對於"="和"==",在hive中where語句中測試了一下是都可以的
(9)---Hive的語法
1)數據類型
2)語法操作
偷懶引用兩個不錯的介紹地址
就先放一張最基礎的create語法供參考
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], ...)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
[
[ROW FORMAT row_format] [STORED AS file_format]
| STORED BY storage.handler.class.name [ WITH SERDEPROPERTIES (...) ] (Note: only available starting with 0.6.0)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)] (Note: only available starting with 0.6.0)
[AS select_statement] (Note: this feature is only available starting with 0.5.0.)
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
LIKE existing_table_name
[LOCATION hdfs_path]
data_type
: primitive_type
| array_type
| map_type
| struct_type
primitive_type
: TINYINT
| SMALLINT
| INT
| BIGINT
| BOOLEAN
| FLOAT
| DOUBLE
| STRING
array_type
: ARRAY < data_type >
map_type
: MAP < primitive_type, data_type >
struct_type
: STRUCT < col_name : data_type [COMMENT col_comment], ...>
row_format
: DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
file_format:
: SEQUENCEFILE
| TEXTFILE
| RCFILE (Note: only available starting with 0.6.0)
| INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
Apache Software Foundation一臉懵逼學習Hive的使用以及常用語法(Hive語法即Hql語法) - 別先生 - 博客園
(10)---HiveUDF概述(用戶自定義函數)
Hive允許用戶自定義一些函數,供後續調用,Hive的UDF的能力,相當於為HIVE提供了一定的擴展能力,開發者可以通過開發HiveUDF來擴展Hive,實現特定功能。
基本步驟:
-a.創建一個普通java工程,導入hive相關包
(hive安裝包中lib目錄下jar包)
-b.創建一個類繼承UDF
-c.在類中編寫一個公有的evaluate方法,返回值和參數列表任意
(至於為什麼是evaluate方法,在源碼中有所解釋
* Implement one or more methods named {@code evaluate} which will be called by Hive (the exact
* way in which Hive resolves the method to call can be configured by setting a custom {@link
* UDFMethodResolver}). The following are some examples:
)
-d.將寫好的工程打成jar包,上傳到linux中
-e.在hive中註冊jar
add jar /home/software/myUDF.jar
-f.註冊自定義函數
create temporary function urlEncode as cn.tedu.hive.udf.URLEncoderUDF;
-g.調用臨時函數
UDF---輸入一行數據輸出一行數據
UDAF---輸入多行數據輸出一行數據,一般在group by中使用
UDTF---udtf用來實現一行輸入多行輸出
(這邊網上的例子很多,知道步驟,要用的時候會用就好)
(11)---Hive的JDBC操作(了解)
a.在服務端手動開啟服務
./hive --service hiveserver2
b.開發jdbc程序,連接hive操作數據
(導包hive-jdbc-1.2.0-standalone.jar、hadoop-common-2.7.1.jar)
package cn.dudu;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
//1.註冊資料庫驅動
Class.forName("org.apache.hive.jdbc.HiveDriver");
//2.獲取資料庫連接
conn=DriverManager.getConnection("jdbc:hive2://hadoopx:10000/park","root","root");
//3.獲取傳輸器
ps=conn.prepareStatement("select * from bucket where id=?");
//設置查詢id為4的值
ps.setInt(1, 4);
//4.傳輸sql執行後去結果集
rs=ps.executeQuery();
//5.遍歷結果集
while(rs.next()) {
String name=rs.getString("name");
System.out.println(name);
}
//6.關閉資源
} catch (Exception e) {
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
rs = null;
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
ps = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
conn = null;
}
}
}
}
}
推薦閱讀: