文章目錄
Hive 簡介
- Hive 數據倉庫
- Hive 解釋器,編譯器,優化器
- Hive 運行時,元數據存儲在關係型數據庫裏面
Hive 架構
CLI: command line interface 命令行接口
JDBC/ODBC: Java 連接數據庫(MySQL、Oracle)
Web GUI: Hive web 用戶界面
metastore:表、字段的約束
Driver: Driver 服務,負責 Hadoop 和 Hive 之間的聯繫()
(1)用戶接口主要有三個:CLI,Client 和 WUI。其中最常用的是CLI,Cli啓動的時候,會同時啓動一個Hive副本。Client是Hive的客戶端,用戶連接至Hive Server。在啓動 Client模式的時候,需要指出Hive Server所在節點,並且在該節點啓動Hive Server。 WUI是通過瀏覽器訪問Hive。
(2)Hive將元數據存儲在數據庫中,如mysql、derby。Hive中的元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否爲外部表等),表的數據所在目錄等。
(3)解釋器、編譯器、優化器完成HQL查詢語句從詞法分析、語法分析、編譯、優化以及查詢計劃的生成。生成的查詢計劃存儲在HDFS中,並在隨後有MapReduce調用執行。
(4)Hive的數據存儲在HDFS中,大部分的查詢、計算由MapReduce完成(包含*的查詢,比如select * from tbl不會生成MapRedcue任務)。
Hive 的架構
編譯器將一個Hive SQL轉換操作符
操作符是Hive的最小的處理單元
每個操作符代表HDFS的一個操作或者一道MapReduce作業
Operator
Operator都是hive定義的一個處理過程
Operator都定義有:
protected List <Operator<? extends Serializable >> childOperators;
protected List <Operator<? extends Serializable >> parentOperators;
protected boolean done; // 初始化值爲false
- ANTER 詞法語法分析工具解析 SQL
Hive 搭建模式
單機模式
通過網絡連接到一個數據庫中
搭建環境準備:
HOST/Soft | MySQL | Hive |
---|---|---|
node01 | * | |
hode02 | * |
搭建過程步驟:
-
安裝 MySQL
# 安裝 mysql 服務 yum install mysql-server -y # 輸入 msyql 會出現這樣的錯誤信息, 原因是 mysqld 服務未啓動 # ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2) # 啓動 mysqld 服務 service mysqld start # 配置 mysql 遠程連接以及用戶名和密碼 grant all privileges on *.* to root@'%' identified by '123' with grant option; # 刷新權限 flush privileges; # 刪除 mysql.user 表中的除了遠程連接用戶外其他用戶的記錄 delete from user where mysql.host != '%' # 查看 mysql 用戶表 select host,user,password from mysql.user
-
安裝 Hive
# 安裝 hive
# 上傳 hive 壓縮包並解壓
tar -zxvf hive.x.y.z.tar.gz
# 移動到 /opt/sxt 目錄下
mv hive.x.y.z /opt/sxt
# 配置 hive 環境變量,編輯 vi /etc/profile 文件
export HIVE_HOME=/opt/sxt/hive.x.y.z
export PATH=$PATH:$HIVE_HOME/bin
# 使 /etc/profile 生效
. /etc/profile
# 輸入 hive 命令,查看 hive 是否安裝成功
# 修改配置文件
cp hive-.xml hive-site.xml
vi hive-site.xml
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive_remote/warehouse</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node01/hive_remote?createDatabaseIfNotExist=true</value>
</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>123</value>
</property>
# 更新 jar 資源
# 將 jline.jar 調整爲高版本,同時將 hadoop 的低版本刪除
cd $HODOOP_HOME/share/hadoop/yarn/lib/
rm -fr jline-0.9.94.jar
cp $HIVE_HOME/lib/jline-2.12.jar ./
# 啓動
hive
分佈式模式
用於非Java客戶端訪問元數據庫,在服務器端啓動 MetaStoreServer,客戶端利用 Thrift 協議通過MetaStoreServer訪問元數據庫
搭建環境準備:
mysql | hive-server | hive-client | |
---|---|---|---|
node01 | * | ||
node03 | * | ||
node04 | * |
搭建步驟:
# 搭建分佈式 Hive 是建立在單機模式之上
# 從之前的 node02 節點上拷貝 $HIVE_HOME 目錄 到 node03、node04 上
# 其中 node03 作爲 Hive 服務端, node04 作爲 Hive 客戶端
scp -r apache-hive-1.2.1-bin/ root@node03:`pwd`/
scp -r apache-hive-1.2.1-bin/ root@node04:`pwd`/
# 配置 node03 node04 的 HIVE 環境變量
# 更新 jar 資源
# 將 jline.jar 調整爲高版本,同時將 hadoop 的低版本刪除
cd $HODOOP_HOME/share/hadoop/yarn/lib/
rm -fr jline-0.9.94.jar
cp $HIVE_HOME/lib/jline-2.12.jar ./
# 在 node03 上 啓動 hive metastore 服務
hive --service metastore
# 在 node04 上啓用 hive 客戶端
hive
配置環境變量的目的:
- 找可執行性文件
- 方便其他框架或者服務使用。 eg: HIVE 通過 HADOOP 的環境變量連接到 Hadoop 上
Hive 之 DDL
官方文檔地址:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-Overview
DDL 語法
- 創建表
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later)
[(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])]
[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]
[SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)]
ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
[STORED AS DIRECTORIES]
[
[ROW FORMAT row_format]
[STORED AS file_format]
| STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later)
]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later)
[AS select_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
LIKE existing_table_or_view_name
[LOCATION hdfs_path];
data_type
: primitive_type
| array_type
| map_type
| struct_type
| union_type -- (Note: Available in Hive 0.7.0 and later)
primitive_type
: TINYINT
| SMALLINT
| INT
| BIGINT
| BOOLEAN
| FLOAT
| DOUBLE
| DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later)
| STRING
| BINARY -- (Note: Available in Hive 0.8.0 and later)
| TIMESTAMP -- (Note: Available in Hive 0.8.0 and later)
| DECIMAL -- (Note: Available in Hive 0.11.0 and later)
| DECIMAL(precision, scale) -- (Note: Available in Hive 0.13.0 and later)
| DATE -- (Note: Available in Hive 0.12.0 and later)
| VARCHAR -- (Note: Available in Hive 0.12.0 and later)
| CHAR -- (Note: Available in Hive 0.13.0 and later)
array_type
: ARRAY < data_type >
map_type
: MAP < primitive_type, data_type >
struct_type
: STRUCT < col_name : data_type [COMMENT col_comment], ...>
union_type
: UNIONTYPE < data_type, data_type, ... > -- (Note: Available in Hive 0.7.0 and later)
row_format
: DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
[NULL DEFINED AS char] -- (Note: Available in Hive 0.13 and later)
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
file_format:
: SEQUENCEFILE
| TEXTFILE -- (Default, depending on hive.default.fileformat configuration)
| RCFILE -- (Note: Available in Hive 0.6.0 and later)
| ORC -- (Note: Available in Hive 0.11.0 and later)
| PARQUET -- (Note: Available in Hive 0.13.0 and later)
| AVRO -- (Note: Available in Hive 0.14.0 and later)
| JSONFILE -- (Note: Available in Hive 4.0.0 and later)
| INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
column_constraint_specification:
: [ PRIMARY KEY|UNIQUE|NOT NULL|DEFAULT [default_value]|CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]
default_value:
: [ LITERAL|CURRENT_USER()|CURRENT_DATE()|CURRENT_TIMESTAMP()|NULL ]
constraint_specification:
: [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
[, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
[, CONSTRAINT constraint_name FOREIGN KEY (col_name, ...) REFERENCES table_name(col_name, ...) DISABLE NOVALIDATE
[, CONSTRAINT constraint_name UNIQUE (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
[, CONSTRAINT constraint_name CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]
練習:
create table psn
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':';
load data local inpath '/root/data/data' into table psn;
-- 查看錶結構
desc formatted 表名
Hive 表
內部表
create table psn3
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by '\001'
collection items terminated by '\002'
map keys terminated by '\003';
外部表
create external table psn4
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':'
location '/data/hive/input/';
區別*
內部表 MANAGED | 外部表 EXTERNAL | |
---|---|---|
創建表時 | 直接存儲在默認的hdfs路徑 | 需要自己指定路徑 |
刪除表時 | 將數據和元數據全部刪除 | 只刪除元數據,數據不刪除 |
先有表,後有數據,使用內部表。先有數據,後有表,使用外部表。
注意:
- 刪除外部表中不會刪除 HDFS 中的數據
- Hive 讀時檢查(解耦,便於數據讀取); 關係數據庫 寫時檢查
Hive 分區
分區表的意義在於優化查詢。查詢時儘量利用分區字段。如果不使用分區字段,就會全部掃描。
注意:分區屬於元數據,不能通過外部表直接從 HDFS 加載 Hive 中,必須在表定義時指定對應的partition字段
分區建表
a. 單分區建表語句:
create table day_table (id int, content string) partitioned by (dt string);
單分區表,按天分區,在表結構中存在 id,content,dt 三列。
以 dt 爲文件夾區分
b. 雙分區建表語句:
create table day_hour_table (id int, content string) partitioned by (dt string, hour string);
雙分區表,按天和小時分區,在表結構中新增加了 dt 和 hour 兩列。
先以 dt 爲文件夾,再以 hour 子文件夾區分
添加分區表語法
(表已創建,在此基礎上添加分區):
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION ‘location1’] partition_spec [LOCATION ‘location2’] …;
- partition_spec:
- (partition_column = partition_col_value, partition_column = partition_col_value, …)
例:
ALTER TABLE day_table ADD PARTITION (dt='2008-08-08', hour='08')
刪除分區
LTER TABLE table_name DROP partition_spec, partition_spec,…
partition_spec:
: (partition_column = partition_col_value, partition_column = partition_col_value, …)
用戶可以用 ALTER TABLE DROP PARTITION 來刪除分區。
內部表中、對應分區的元數據和數據將被一併刪除。
例:
ALTER TABLE day_hour_table DROP PARTITION (dt='2008-08-08', hour='09');
向指定分區添加數據語法
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE]
INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
例:
-- 從 HDFS 中加載數據
LOAD DATA INPATH '/user/pv.txt'
INTO TABLE day_hour_table PARTITION(dt='2008-08- 08', hour='08');
-- 從本地文件系統中加載數據
LOAD DATA local INPATH '/user/hua/*'
INTO TABLE day_hour partition(dt='2010-07- 07');
當數據被加載至表中時,不會對數據進行任何轉換。
Load 操作只是將數據複製至 Hive 表對應的位置。數據加載時在表下自動創建一個目錄。
查詢執行分區語法
SELECT day_table.* FROM day_table WHERE day_table.dt>= '2008-08-08';
分區表的意義在於優化查詢。查詢時儘量利用分區字段。如果不使用分區字段,就會全部掃描。
Hive查詢表的分區信息語法
SHOW PARTITIONS day_hour_table;
預先導入分區數據,但是無法識別怎麼辦?
Msck repair table tablename
直接添加分區
動態分區
-
開啓支持動態分區
set hive.exec.dynamic.partition=true;
默認:true
set hive.exec.dynamic.partition.mode=nostrict;
默認:strict(至少有一個分區列是靜態分區)
相關參數set hive.exec.max.dynamic.partitions.pernode;
每一個執行mr節點上,允許創建的動態分區的最大數量(100)
set hive.exec.max.dynamic.partitions;
所有執行mr節點上,允許創建的所有動態分區的最大數量(1000)
set hive.exec.max.created.files;
所有的mr job允許創建的文件的最大數量(100000)
-
加載數據
create external table psn21( id int, name string, sex string, age int, likes array<string>, address map<string,string> ) row format delimited fields terminated by ',' collection items terminated by '-' map keys terminated by ':' location '/data/bucket/input'; create table psn22( id int, name string, likes array<string>, address map<string,string> ) partitioned by (age int,sex string) row format delimited fields terminated by ',' collection items terminated by '-' map keys terminated by ':'; # hive 命令行中設置動態分區爲非嚴格模式 set hive.exec.dynamic.partition.mode=nonstrict # 注意: 參數的位置要對應 from psn21 insert overwrite table psn22 partition(age, sex) select id, name, likes, address, age,sex distribute by age, sex;
Hive 之 DML*
官方文檔地址:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML#LanguageManualDML-HiveDataManipulationLanguage
加載數據的方式
-
Loading files into tables 從文件中加載數據
Hive does not do any transformation while loading data into tables. Load operations are currently pure copy/move operations that move datafiles into locations corresponding to Hive tables.
語法:
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] [INPUTFORMAT 'inputformat' SERDE 'serde'] (3.0 or later)
注意: 從 HDFS 中加載數據,數據發生移動,而從本地加載數據,數據發生拷貝。
-
Inserting data into Hive Tables from queries 從查詢結果集中加載數據
Query Results can be inserted into tables by using the insert clause.
語法:
Standard syntax:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
Hive extension (multiple inserts):
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2]
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2] ...;
FROM from_statement
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2]
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2] ...;
Hive extension (dynamic partition inserts):
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;
INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;
例子:
FROM psn
INSERT OVERWRITE TABLE psn10
SELECT id,name
insert into psn11
select id,likes
insert overwrite local directory '/root/result'
select * from psn;
更新操作
- ACID 事務的特性
- 三大範式
Hive SerDe
SerDe 用於做序列化和反序列化。
構建在數據存儲和執行引擎之間,對兩者實現解耦。
Hive通過 ROW FORMAT DELIMITED 以及 SERDE 進行內容的讀寫。
row_format
: DELIMITED
[FIELDS TERMINATED BY char [ESCAPED 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, ...)]
Hive 正則匹配
CREATE TABLE logtbl (
host STRING,
identity STRING,
t_user STRING,
time STRING,
request STRING,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)"
)
STORED AS TEXTFILE;
Hive Beeline
提供了 JDBC 的訪問方式
beenline 不能用於 DML 操作,只能執行一些查詢操作
-- 第一種方式
beeline
!connect jdbc:hive2://node04:10000/default root 123
-- 第二種方式
beeline -u connect jdbc:hive2://node04:10000/default -n root
Hive JDBC
public class HiveDemo {
// private final static String driver = "org.apache.hive.jdbc.HiveDriver";
// private final static String url = "jdbc:hive2://node04:10000/default";
// private final static String username = "root";
// private final static String password = "123";
public static void main(String[] args) {
try {
Properties prop = new Properties();
prop.load(new FileInputStream(new File("jdbc.properties")));
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
Class.forName(driver);
Connection conn = DriverManager.getConnection(url,username,password);
Statement st = conn.createStatement();
String sql = "select * from psn";
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println(id+"\t"+name);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Hive 函數
官方文檔地址:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
自定義 UDF
官方文檔地址:
https://cwiki.apache.org/confluence/display/Hive/HivePlugins
- java 代碼
public class TuoMing extends UDF{
public Text evaluate(final Text s) {
if (s == null) {
return null;
}
String str = s.toString().substring(0, 3) + "***";
return new Text(str);
}
}
-
將 java 代碼文件打包成 jar ,上傳 Linux 上的 HDFS 中
-
創建臨時函數
-- 本地文件系統加載 add jar /root/tm/tm.jar; create temporary function tm as 'com.szxy.hive.TuoMing'; -- 從 HDFS 中加載 create temporary function tms as 'com.szxy.hive.TuoMing' using jar 'hdfs://node01:8020/data/jar/tm/tm.jar';
-
使用臨時函數
select tms(name) from psn;
-
結果
Hive 案例
struct 結構體
-
測試數據
1001,zhangsan:24 1002,lisi:25 1003,wangwu:26 1004,zhaoliu:27
-
創建表
create table student( id int, info struct<name:string,age:int>) row format delimited fields terminated by "," collection items terminated by ":"; load data inpath '/data/struct/input' into table student;
WordCount
create external table hello(
line string
)
location '/data/wc/input'
create table hello_wc(
word string ,
num int
);
from (select explode(split(line,' ')) word from hello ) t
insert into hello_wc
select word,count(word) group by word;
基站掉話率統計
-
需求:
找出掉線率最高的前10基站
-
sql 語句
create table tb_cell_result( imei string, drop_num int, duration int, drop_rate double ); create external table tb_cell( record_time string, imei string, cell string, ph_num int, call_num string, drop_num int, duration int, drop_rate int, net_type string, erl int ) row format delimited fields terminated by ',' location '/data/cell/input'; from tb_cell insert into tb_cell_result select imei,sum(drop_num) sdrop,sum(duration) sdura, sum(drop_num)/sum(duration) srate group by imei sorted by srate desc; select * from tb_cell_result limit 10;
Hive 參數
-
hive 參數、變量
hive當中的參數、變量,都是以命名空間開頭
命名空間 讀寫權限 含義 hiveconf 可讀寫 hive-site.xml 中配置各種變量
例:hive --hiveconf hive.cli.print.header=true
System 可讀寫 系統變量,包括 JVM 運行參數等
例:system:user.name=rootenv 只讀 環境變量“
例:env:JAVA_HOMEhivevar 可讀寫 例:hive -d val=key 通過
${}
方式進行引用,其中 system、env 下的變量必須以前綴開頭 -
hive 參數設置方式
-
修改配置文件
${HIVE_HOME}/conf/hive-site.xml
<property> <name>hive.cli.print.header</name> <value>true</value> </property>
-
啓動 hive cli 時,通過
--hiveconf key=value
的方式進行設置 例:
hive --hiveconf hive.cli.print.header=true
-
進入
cli
之後,通過使用set命令設置set hive.cli.print.header=true;
-
Hive 分桶
分桶概念
-
分桶表是對列值取哈希值的方式,將不同數據放到不同文件中存儲。
-
對於hive中每一個表、分區都可以進一步進行分桶。
-
由列的哈希值除以桶的個數來決定每條數據劃分在哪個桶中。
適用場景
數據抽樣( sampling )
分桶操作
-
開啓支持分桶
set hive.enforce.bucketing=true;
默認:false;設置爲 true之後,mr運行時會根據 bucket 的個數自動分配 reduce task 個數。
(用戶也可以通過mapred.reduce.tasks自己設置reduce任務個數,但分桶時不推薦使用)
注意:一次作業產生的桶(文件數量)和reduce task個數一致。 -
往分桶表中加載數據
insert into table bucket_table select columns from tbl; insert overwrite table bucket_table select columns from tbl;
-
桶表 抽樣查詢
select * from bucket_table tablesample(bucket 1 out of 4 on columns);
-
TABLESAMPLE 語法
TABLESAMPLE(BUCKET x OUT OF y)
x:表示從哪個bucket開始抽取數據
y:必須爲該表總bucket數的倍數或因子 -
栗子
當表總 bucket 數爲32時TABLESAMPLE(BUCKET 3 OUT OF 8),抽取哪些數據?
答:共抽取2(32/16)個bucket的數據,抽取第2、第18(16+2)個bucket的數據
TABLESAMPLE(BUCKET 3 OUT OF 256),抽取哪些數據?
分桶案例
-
測試數據
1,tom,11 2,cat,22 3,dog,33 4,hive,44 5,hbase,55 6,mr,66 7,alice,77 8,scala,88
-
創建 hive 表
create external table tb_bucket( id int, name string, score int ) row format delimited fields terminated by ',' location '/data/bucket/input';
-
創建分桶表
create table psn_bucket( id int, name string, score int ) clustered by(score) into 4 buckets row format delimited fields terminated by ',';
-
向分桶表中添加數據
insert into psn_bucket select id,name,score from tb_bucket;
注意:Hive 分桶默認是關閉的,通過
set hive.enforce.bucketing=true;
開啓分桶 -
抽樣
select id,name,score from psn_bucket tablesample(bucket 2 out of 4);
Hive Laternal View
在 UDTF 函數中使用
Lateral View用於和UDTF函數(explode、split)結合來使用。
首先通過UDTF函數拆分成多行,再將多行結果組合成一個支持別名的虛擬表。
主要解決在select使用UDTF做查詢過程中,查詢只能包含單個UDTF,不能包含其他字段、以及多個UDTF的問題
語法:
LATERAL VIEW udtf(expression) tableAlias AS columnAlias (',' columnAlias)
注意: 列別名有多個,並且可以重複
栗子
統計人員表中共有多少種愛好、多少個城市?
select count(distinct(myCol1)), count(distinct(myCol2)) from psn
LATERAL VIEW explode(likes) myTable1 AS myCol1
LATERAL VIEW explode(address) myTable2 AS myCol2, myCol3;
select count(distinct(mycol)) from psn lateral view explode(likes) myTable as mycol;
Hive 視圖
視圖本質上就是一個虛擬表 Virtual Table,和關係型數據庫中的普通視圖一樣,hive也支持視圖
特點:
-
不支持物化視圖
-
只能查詢,不能做加載數據操作
-
視圖的創建,只是保存一份元數據,查詢視圖時才執行對應的子查詢
-
view定義中若包含了ORDER BY/LIMIT語句,當查詢視圖時也進行ORDER BY/LIMIT語句操作,view當中定義的優先級更高
-
view支持迭代視圖
view語法
-
創建視圖:
CREATE VIEW [IF NOT EXISTS] [db_name.]view_name [(column_name [COMMENT column_comment], ...) ] [COMMENT view_comment] [TBLPROPERTIES (property_name = property_value, ...)] AS SELECT ... ;
-
查詢視圖:
select colums from view;
-
刪除視圖:
DROP VIEW [IF EXISTS] [db_name.]view_name
Hive 索引
-
目的
優化查詢以及檢索性能
-
創建索引:
create index t1_index on table psn(name) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild in table t1_index_table; -- as:指定索引器; -- in table:指定索引表,若不指定默認生成在default__psn2_t1_index__表中 create index t1_index on table psn2(name) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild;
-
查詢索引
show index on psn2;
-
重建索引(建立索引之後必須重建索引才能生效)
ALTER INDEX t1_index ON psn REBUILD;
-
刪除索引
DROP INDEX IF EXISTS t1_index ON psn;
Hive 運行方式
-
命令行方式cli:控制檯模式
- 與hdfs交互
執行執行dfs命令
例:dfs –ls /
- 與Linux交互
!開頭
例:!pwd
- 與hdfs交互
-
腳本運行方式(實際生產環境中用最多)
hive -e "" hive -e "">aaa hive -S -e "">aaa hive -f file hive -i /home/my/hive-init.sql hive> source file (在hive cli中運行)
-
JDBC方式:hiveserver2
-
web GUI接口 (hwi、hue等)
Hive 權限管理
官方文檔地址:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Authorization
三種授權模型:
-
Storage Based Authorization in the Metastore Server
基於存儲的授權 - 可以對Metastore中的元數據進行保護,但是沒有提供更加細粒度的訪問控制(例如:列級別、行級別)。
-
SQL Standards Based Authorization in HiveServer2
基於SQL標準的Hive授權 - 完全兼容SQL的授權模型,推薦使用該模式。
https://cwiki.apache.org/confluence/display/Hive/SQL+Standard+Based+Hive+Authorization -
Default Hive Authorization (Legacy Mode)
hive默認授權 - 設計目的僅僅只是爲了防止用戶產生誤操作,而不是防止惡意用戶訪問未經授權的數據。
SQL Standards Based Authorization in HiveServer2
-
完全兼容SQL的授權模型
-
除支持對於用戶的授權認證,還支持角色 role 的授權認證
role可理解爲是一組權限的集合,通過role爲用戶授權
一個用戶可以具有一個或多個角色
默認包含另種角色:public、admin
-
限制:
1、啓用當前認證方式之後,dfs, add, delete, compile, and reset等命令被禁用。2、通過set命令設置hive configuration的方式被限制某些用戶使用。
(可通過修改配置文件hive-site.xml中hive.security.authorization.sqlstd.confwhitelist進行配置)
3、添加、刪除函數以及宏的操作,僅爲具有admin的用戶開放。
4、用戶自定義函數(開放支持永久的自定義函數),可通過具有admin角色的用戶創建,其他用戶都可以使用。
5、Transform功能被禁用。
-
在hive服務端修改配置文件hive-site.xml添加以下配置內容:
<property> <name>hive.security.authorization.enabled</name> <value>true</value> </property> <property> <name>hive.server2.enable.doAs</name> <value>false</value> </property> <property> <name>hive.users.in.admin.role</name> <value>root</value> </property> <property> <name>hive.security.authorization.manager</name> <value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value> </property> <property> <name>hive.security.authenticator.manager</name> <value>org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator</value> </property>
服務端啓動hiveserver2;客戶端通過beeline進行連接
Hive 優化*
核心思想:把 Hive SQL 當做Mapreduce程序去優化
以下 SQL 不會轉爲Mapreduce來執行:
-
select 僅查詢本表字段
-
where 僅對本表字段做條件過濾
Explain 顯示執行計劃
EXPLAIN [EXTENDED] query
Hive抓取策略
Hive中對某些情況的查詢不需要使用 MapReduce 計算
抓取策略
Set hive.fetch.task.conversion=none/more;
Hive運行方式
-
本地模式
-
集羣模式
開啓本地模式
set hive.exec.mode.local.auto=true;
注意:
hive.exec.mode.local.auto.inputbytes.max
默認值爲128M
表示加載文件的最大值,若大於該配置仍會以集羣方式來運行
並行計算
通過設置以下參數開啓並行模式:
set hive.exec.parallel=true;
注意:hive.exec.parallel.thread.number
(一次SQL計算中允許並行執行的job個數的最大值)
嚴格模式
- 通過設置以下參數開啓嚴格模式:
set hive.mapred.mode=strict;
(默認爲:nonstrict非嚴格模式)
-
查詢限制
1、對於分區表,必須添加where對於分區字段的條件過濾;
2、order by語句必須包含limit輸出限制;
3、限制執行笛卡爾積的查詢。
Hive排序
- Order By - 對於查詢結果做全排序,只允許有一個reduce處理
(當數據量較大時,應慎用。嚴格模式下,必須結合limit來使用) - Sort By - 對於單個reduce的數據進行排序
- Distribute By - 分區排序,經常和Sort By結合使用
- Cluster By - 相當於 Sort By + Distribute By
(Cluster By不能通過asc、desc的方式指定排序規則;
可通過 distribute by column sort by column asc|desc 的方式)
Hive Join
Join計算時,將小表(驅動表)放在join的左邊
Map Join:在Map端完成Join
兩種實現方式:
- SQL方式,在SQL語句中添加 MapJoin 標記(mapjoin hint)
語法:
SELECT /*+ MAPJOIN(smallTable) */ smallTable.key, bigTable.value
FROM smallTable JOIN bigTable ON smallTable.key = bigTable.key;
-
開啓自動的MapJoin
自動的mapjoin
通過修改以下配置啓用自動的 mapjoin:set hive.auto.convert.join = true;
(該參數爲true時,Hive 自動對左邊的表統計量,如果是小表就加入內存,即對小表使用 Map join)
相關配置參數:
hive.mapjoin.smalltable.filesize;
(大表小表判斷的閾值,如果表的大小小於該值則會被加載到內存中運行)
hive.ignore.mapjoin.hint;
(默認值:true;是否忽略mapjoin hint 即mapjoin標記)
hive.auto.convert.join.noconditionaltask;
(默認值:true;將普通的join轉化爲普通的mapjoin時,是否將多個mapjoin轉化爲一個mapjoin)
hive.auto.convert.join.noconditionaltask.size;
(將多個mapjoin轉化爲一個mapjoin時,其表的最大值)
注意:
hive.exec.parallel.thread.number
(一次SQL計算中允許並行執行的job個數的最大值)- 儘可能使用相同的連接鍵(會轉化爲一個MapReduce作業)
-
大表join大表
空key過濾:有時join超時是因爲某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而導致內存不夠。此時我們應該仔細分析這些異常的key,很多情況下,這些key對應的數據是異常數據,我們需要在SQL語句中進行過濾。
空key轉換:有時雖然某個key爲空對應的數據很多,但是相應的數據不是異常數據,必須要包含在join的結果中,此時我們可以表a中key爲空的字段賦一個隨機的值,使得數據隨機均勻地分不到不同的reducer上
Map-Side聚合
通過設置以下參數開啓在Map端的聚合:
set hive.map.aggr=true;
相關配置參數:
hive.groupby.mapaggr.checkinterval:
map 端 group by 執行聚合時處理的多少行數據(默認:100000)
hive.map.aggr.hash.min.reduction:
進行聚合的最小比例(預先對100000條數據做聚合,若聚合之後的數據量/100000的值大於該配置0.5,則不會聚合)
hive.map.aggr.hash.percentmemory:
map端聚合使用的內存的最大值
hive.map.aggr.hash.force.flush.memory.threshold:
map端做聚合操作是hash表的最大可用內容,大於該值則會觸發flush
hive.groupby.skewindata
是否對GroupBy產生的數據傾斜做優化,默認爲false
相關配置參數:
hive.groupby.mapaggr.checkinterval:
map端group by執行聚合時處理的多少行數據(默認:100000)
hive.map.aggr.hash.min.reduction:
進行聚合的最小比例(預先對100000條數據做聚合,若聚合之後的數據量/100000的值大於該配置0.5,則不會聚合)
hive.map.aggr.hash.percentmemory:
map端聚合使用的內存的最大值
hive.map.aggr.hash.force.flush.memory.threshold:
map端做聚合操作是hash表的最大可用內容,大於該值則會觸發flush
hive.groupby.skewindata
是否對GroupBy產生的數據傾斜做優化,默認爲false
合併小文件
文件數目小,容易在文件存儲端造成壓力,給hdfs造成壓力,影響效率
-
設置合併屬性
是否合併map輸出文件:hive.merge.mapfiles=true
是否合併reduce輸出文件:hive.merge.mapredfiles=true;
合併文件的大小:hive.merge.size.per.task=25610001000 -
去重統計
數據量小的時候無所謂,數據量大的情況下,由於 COUNT DISTINCT 操作需要用一個 Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換
控制Hive中Map以及Reduce的數量
-
Map 數量相關的參數
參數設置 解釋 mapred.max.split.size 一個split的最大值,即每個map處理文件的最大值 mapred.min.split.size.per.node 一個節點上split的最小值
| mapred.min.split.size.per.rack | 一個機架上split的最小值 |
- Reduce 數量相關的參數
參數 解釋 mapred.reduce.tasks 強制指定reduce任務的數量 hive.exec.reducers.bytes.per.reducer 每個reduce任務處理的數據量 hive.exec.reducers.max 每個任務最大的reduce數
Hive- JVM重用
適用場景:
1、小文件個數過多
2、task個數過多
通過 set mapred.job.reuse.jvm.num.tasks=n;
來設置
(n爲task插槽個數)
缺點:
設置開啓之後,task插槽會一直佔用資源,不論是否有task運行,
直到所有的 task 即整個 job 全部執行完成時,纔會釋放所有的 task 插槽資源!