Hive是一種用於執行離線計算的數據倉庫工具,基於Hadoop的HDFS與MR實現。html
Hive偏重於數據的分析和處理,使用映射關係將結構化的數據映射爲表的結構。java
例如:基於數據(1,zhangsan,123456,男)對應生成(id+uname+pwd+sex)的映射mysql
linux
Hive可以實現非Java用戶對HDFS數據的MR操做。web
分爲OLAP聯機分析處理,OLTP聯機事務處理sql
經過對以往數據的分析,對現有和將來業務提供數據支持數據庫
對數據處理分爲:apache
OLAP聯機事務處理,負責數據事務處理,關係型數據庫的主要應用json
OLAP聯機分析處理,負責數據分析處理,數倉的主要應用
數倉中的數據模型包括:
星型模式(單一中心節點)
雪花模型(一箇中心節點多個分支節點)
星系模型(多中心節點)
數倉基本用於執行對數據的查找和統計,通常不會刪除數據或修改數據
client
客戶端包括三種方式
命令行模式——直接經過HQL(Hive Sql)執行操做
JDBC/ODBC模式——經過java代碼操做,需藉助ThriftServer將代碼轉爲HQL
WebUI——經過web端輸入HQL,遠程執行任務
MetaStore
元數據存儲器,用於存儲Hive建表語句,也就是描述Hive與數據的映射關係的數據
元數據包括:表,表的列、分區、屬性、表的屬性,表的數據所在目錄
元數據會存放在關係型數據庫中(mysql)
Driver
解析器——將hql解析爲語法樹
編譯器——將語法樹轉換爲邏輯執行計劃
優化器——重寫邏輯執行計劃實現優化
執行器——將邏輯執行計劃轉換爲物理執行計劃(MR-JOB)
基於Hadoop-Yarn+Mapredce+Hdfs執行物理執行計劃
前提:mysql與Hadoop安裝完成
在mysql中添加一個庫用於存放Hive的映射
create database hive_single;
將安裝包解壓到指定位置
tar -zxvf apache-hive-1.2.1-bin.tar.gz
cp -r apache-hive-1.2.1-bin /opt/sxt/
mv apache-hive-1.2.1-bin hive-1.2.1
修改配置文件
cp hive-default.xml.template hive-site.xml
刪除原始內容中configuration標籤下的內容(3891行)填入以下內容
<!--hive數據在hdfs中的路徑-->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/hive_single</value>
</property>
<!--是否本地單機模式-->
<property>
<name>hive.metastore.local</name>
<value>true</value>
</property>
<!--mysql鏈接,須要指定數據庫名,例如hive_single-->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive_single?createDatabaseIfNotExist=true</value>
</property>
<!--mysql驅動、用戶名、密碼,注意這個是liunx中安裝的mysql-->
<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>
拷貝mysql的jar包到lib目錄(mysql-connector-java-5.1.32-bin.jar)
解決Hadoop與Hive的jar版本差別(將jline文件替換)
cd /opt/sxt/hadoop-2.6.5/share/hadoop/yarn/lib/
rm -rf jline-0.9.94.jar
cp /opt/sxt/hive-1.2.1/lib/jline-2.12.jar ./
配置PATH
vim /etc/profile
export HIVE_HOME=/opt/sxt/hive-1.2.1 export PATH=$HIVE_HOME/bin:$PATH(注意加上其餘軟件的路徑)
source /etc/profile
Hive啓動命令:hive
查看庫命令show databases;
建立庫create database myhive;
使用庫use myhive;
建立表create table user;
保存快照
HQL語句結尾要加分號;
進入命令行 hive
清空頁面 !clear;
DDL用於執行數據庫組件的定義(建立修改刪除)
DDL須要注意庫,表字段命名的規範
DDL官方文檔https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL
整型
int(4byte) tinyint(1bety) smallint(2byte)bigint(8byte)
浮點型
double(8byte) float(4byte)
字符型
string char(定長) varchar(不定長)
boolean型
true/false (1位)
時間型
timestamp時間戳 date日期
自動
整型隱式轉爲範圍大的整型
全部整型,float,string能夠隱式轉爲double
int,tinyint,smallint能轉爲double
double不能轉型爲其餘數據類型
強制
例如:cast('1' as int)
表設計時須設置合適的數據類型避免類型轉型
由基本類型構成,複合類型能夠相互嵌套
Array
存放相同類型的數據
以索引排序,索引從0開始
獲取數據的格式爲:user[0]
Map
存儲任意數量的鍵值對,適用屬性的數量和類型均不肯定的狀況
經過key取值,map['key1']
key不能相同,相同的key會相互覆蓋
Struct
結構體,內部的屬性與屬性的類型固定
經過屬性獲取值:info.name(獲取info結構體中name的屬性)
建立數據庫
create database sxt;
create database if not exists sxt;
create database sxt location '/hive_single/sxt_path' 指定數據庫在hdfs的路徑(路徑名與數據庫名可不一樣,建立時不會將原路徑數據清除)
刪除數據庫
drop database if exists sxt cascade;
刪除庫,並將庫所在文件夾刪除
drop database sxt ;
刪除空庫
使用數據庫
use sxt ;
查看數據庫
show databases;查看全部數據庫名
show databases like 's*'; 匹配查找數據庫
desc database sxt;查看庫內的表
修改數據庫(瞭解)
沒法修改數據庫名和數據庫所在路徑。只能修改其餘數據
alter database sxt set dbproperties('createtime'='20170830');
external 是不是外部表,不加該關鍵字則默認內部表
定義每一列
全部列在括號內,相互經過逗號分隔
(col_name data_type [COMMENT col_comment], ...)
普通列: name string
數組: books array< string>
map: score map<string,int>
struct: info struct< name:String,age:int>
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
字段分隔,array分隔,結構體與map的K-V分隔符,行分隔符
注意順序不能改變
默認行以\n分隔,能夠省略
ROW FORMAT delimited
fields terminated by ','
collection items terminated by '_'
map keys terminated by ':'
lines terminated by '\n';
數據存儲格式
STORED AS file_format 用於數據壓縮等狀況
數據文件的地址
LOCATION hdfs_path
內部表和外部表均能指定表HDFS路徑,LOCATION 是一個文件夾
location '/hive_single/sxt';
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]
[LOCATION hdfs_path]
實例:
文本格式:
songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing
yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing
json格式:
{
"name": "songsong",
"friends": ["bingbing" , "lili"] , //列表Array,
"children": { //鍵值Map,
"xiao song": 18 ,
"xiaoxiao song": 19
}
"address": { //結構Struct,
"street": "hui long guan" ,
"city": "beijing"
}
}
create table person(
name string,
friends array<String>,
children map<String,int>,
address struct<street:string,city:string>
)
row format delimited fields terminated by ','
collection items terminated by '_'
map keys terminated by ':'
lines terminated by '\n'
表默認爲內部表,使用external則爲外部表
表建立時都不會將已有文件夾中的數據清除。
內部表
內部表處理獨享的數據,適用於單次處理的數據,不適合於其餘工具共享數據
刪除表時表路徑中的原始數據也會刪除,若指定location的內部表會將location的一級目錄刪除
外部表
定義表可定義location路徑,實現和其餘表共享數據文件
刪除外部表時只刪除元數據信息,location目錄下的數據將被保留
create external table person(name string)
location '/myhive/sxt';
內外表切換
alter table sxt set tblproperties('EXTERNAL'='TRUE'); 內轉外
alter table sxt set tblproperties('EXTERNAL'='FALSE'); 外轉內
表刪除(外部表不清除原始數據)
drop table [if exsits] t_user;
清空表數據,直接截斷
truncate table_name;
查看錶結構
desc table_name ;
表修改(瞭解)
改表名
alter table t_oldName rename to t_newName;
內部表會將對應文件目錄名修改,若指定了location則將location原目錄移動到默認路徑下
外部表不會影響location地址的數據,不指定location也不會對默認路徑進行修改
更新列
alter table table_name change [column] col_oldName col_newName column_type [column col_comment] [FIRST|AFTER column_name];
增長替換列
alter table table_name add|replace columns(col_name data_type [備註], ...);
load data [local] inpath '/root/path' [overwrite] into table table_name
local,表示路徑爲linux路徑,不然默認爲HDFS路徑
overwrite,表示覆蓋載入,將表文件中原有的數據覆蓋,不然默認爲追加
load 加載不執行MR操做
local文件將被複制到HDFS的表目錄中,HDFS文件則剪切到表目錄。
insert會啓動MR操做,通常用於將原表的查詢結果插入到新表中。
overwrite(覆蓋) 和 into(追加),能夠相互替換
單表插入
insert overwrite table t2 select xxx from t1;(將表1的xxx字段插入表2中)
多表插入
from t1
insert overwrite table t2 select xxx1
insert overwrite table t3 select xxx2; (將表1的xxx字段插入表2中)
單記錄插入(通常不這麼作)
insert into t1 values ('id','5'),('name','zhangwuji');
計算導出
經過insert將查詢結果保存爲數據文件,執行了MR操做且只保存數據文件
insert overwrite local directory '/root/data_out'
row format delimited fields terminated by '-'
select * from mytable;
加入local表示導出到本地 linux的文件路徑中,不加location則表示導出到HDFS的文件路徑中
row format部分表示輸出數據的間隔方式,與表定義相似
直接導出
導出,將表數據及表結構指定hdfs路徑下,在該路徑下保存元數據文件與數據文件夾。
export table t_name to '/hdfs_path'
導入,將文件夾導入到命名空間,直接在命名空間下生成導出的表及數據
import from '/hdfs_path'
恢復後的文件夾名與表名相同,表自生屬性也被保留(外部表屬性,內部字段等)
爲了減小全表掃描查詢的問題,根據指定字段的值,對數據進行分區存儲(分多個文件夾存儲)
--定義分區表時,能夠指定多個分區屬性
create table t_name(id int,name string)
partitioned by (addr string , work string)
row format delimited fields terminated by ',';
分區層級分爲:單分區和多分區
單分區:只有一種分區。按照單一屬性值分區
多分區,包含存在父子關係的多種分區。先依據父級屬性分區,再依據子級屬性分區
分區操做
添加分區 alter table t_name add partition(column='xxx');
刪除分區 alter table t_name drop partition(column='xxx');
查詢分區 show partitions t_name;
數據載入
load data [local] inpath '/path' into table 't_name' partition (column1='xxx',column2='yyy');
靜態載入的數據,會複製到對應的分組文件夾下,若無則自動建立文件夾。
數據只能載入到一個文件夾中,且查詢時hive直接從文件夾中取數據,再也不對分組字段處理。若文件中存在分組字段實際數據與分組數據不匹配,也將該字段值視爲指定的分組數據。
開啓動態分區指定以下
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
開啓動態分區後再建立主分區表
create table table1( id int, name string ) partitioned by (novel string,sect string) row format delimited fields terminated by ',' ;
建立外部臨時表,臨時表的字段與主分區表字段相同,臨時表的location指向數據源
create external table table2 ( id int, name string, novel string, sect string ) row format delimited fields terminated by ',' location '/path' ;
使用insert語句經過臨時表將數據載入主表,期間執行的MR操做
insert overwriter table table1 partition(novel,sect) select id,name,novel,sect from table2;
根據指定的列,對列值hash計算,根據結果將數據存入對應桶,可以將數據有效散列到桶中。分桶須要執行MR,桶的數量與reduce相同,計算結果輸出到對應的桶文件中。
效果:使得桶中的數據較爲均勻,便於統計計算。相同的key必然在一個桶中,下降表鏈接的數量。
數據插入:依賴於insert方式的數據插入。
指定列須要知足:常常被查詢,自身散列較好
分桶能夠在分區的基礎上執行
分桶的數據須要具有較多的公約數,便於查詢(12的公約數:1,2,3,4,6)
分桶建表語句
create table table01( id int ,name string,age int) clustered by (name) sorted by (age) into 6 buckets ROW FORMAT DELIMITED FIELDS TERMINATED BY ','; --說明 按照name屬性分桶,桶內經過age實現排序
分桶表的取樣SQL
tablesample(bucket x out of y on 分桶列 )
第二個參數表示將桶分爲多少組,其爲分桶數的公約數
第一個參數表示每一個組中取幾個桶進行計算
參數1不大於參數2
select * from table01 tablesample(bucket 1 out of 3 on name );
經過正則將列與複雜數據進行映射,可以匹配複雜文本
--基本格式 create table table_name(column type,...) row fromat serde 'org.apache.hadoop.hive.serde2.RegexSerDe' with serdeproperties("input.regex" ="正則")
正則中每一個括號內的部分對應前面定義的列
例子以下:
原始文件格式: 192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-upper.png HTTP/1.1" 304 - 192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /bg-nav.png HTTP/1.1" 304 - 192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] "GET /asf-logo.png HTTP/1.1" 304 -
--建表語句 create table t_log( host string, identity1 string, identity2 string, time string, request string, referer string, agent string,) row fromat serde 'org.apache.hadoop.hive.serde2.RegexSerDe' with serdeproperties( "input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)" )
映射說明: 括號內的內容匹配每一個列,對應關係以下 host 192.168.57.4 identity1 - identity2 - time 29/Feb/2016:18:14:35 +0800 request GET referer /bg-upper.png HTTP/1.1 agent 304
SQL 語言大小寫不敏感。
SQL 能夠寫在一行或者多行
關鍵字不能被縮寫也不能分行
各子句通常要分行寫,注意tab鍵會致使命令異常
Hive SQL的使用和數據庫SQL基本上是同樣的
錶鏈接支持99語法
排序
sorted by 對deduce數據的數據進行排序
order by 對所有數據進行排序
分頁
limit x 展現前x行記錄,與排序組合實現展現最大(小)值
limit x,y 展現x-y行記錄
組函數
max min avg sum count 組函數通常與group by組合使用
選擇函數
nvl(obj,default) 單行選擇函數
至關於obj==null?default:obj,若obj爲空則取默認值,不然取自身的值
split(column,'-') 將字段分隔爲數組,以某個字符串做爲間隔
explode(split(column,'-)) 將分割的數組展開,但不能直接與普通列同時使用
lateral view explode(split(column,'-)) typeTable as xxx 將列展開成表,再與普通列出如今一行
--數據 nezha js,gx,qq,dm meirenyu gx,kh,aq xingjidazhan kh,js huoyingrenzhe dm,qj,yq,aq --表 create table t_movie( name string,type string) row format delimited fields terminated by ' '; --查詢 select name,xxx from t_movie lateral view explode(split(type,',')) tempTable as xxx;
內置運算符
關係運算符
A = B;A is null;A like B
返回boolean
算數運算法
+,-,*,/,%,|,^,~
適用於數值計算
邏輯運算符
and,or,not,&&,|,!
適用於布爾值運算
複雜函數
定義
map(k1,v1,k2,v2...)
struct(v1,v2,v3...)
array(v1,v2,v3)
操做
A[n] 數組A的第n個元素,從0開始
M['key'] 數組M中key對應的值
S.x 結構體S中的x屬性值
內置函數
數字函數
數值計算相關函數,包括取值,隨機,轉進制,絕對值...
字符串函數
長度,分割split,鏈接,大小寫,去空格...
collection函數
size(數組/map) 獲取長度
轉型函數
cast(值 as 目標類型)
日期函數
與字符串轉換,日期的計算相關
條件函數
if(boolean,value1,value2)
內置聚合函數UDAF
count,sum,avg,min,max;
求方差,差值等;
collect_set(col)返回無重複的數據
內置表生成函數UDTF
explode(array) 拆分數組
因爲內置函數不知足咱們的須要,須要自定義函數。(自定義代碼實現對指定的數據進行運算,返回所需的結果,中間可使用java的類庫實現複雜操做)
UDF(User-Defined-Function) 一進一出
UDAF(User- Defined Aggregation Funcation) 彙集函數,多進一出
UDTF(User-Defined Table-Generating Functions) 一進多出(瞭解)
注意:在IDE工具中導入hive依賴jar包 (D:\BigData\課件及軟件\第6階段:Hadoop 離線體系:Hive\軟件\apache-hive-1.2.1-bin\lib)
如下函數均使用臨時函數命令
建立項目,導入hive的jar包,建立java類繼承org.apache.hadoop.hive.ql.exec.UDF
實現public String evaluate(Object value...)方法,該方法爲重載方法,能夠傳入任意類型數據
將項目打成jar文件上傳至linux系統
hive客戶端中,清空之前的同名文件,將上傳的文件添加到hive函數庫中
delete jar /root/xxx.jar
add jar /root/xxx.jar
給自定義函數建名稱,指定到對應的自定義java類
create temporary function xxx as 'com.jay.Xxx'
使用函數
select xxx(empno),xxx(emane) from t_emp;
銷燬函數
drop temporary function xxx;
自定義函數代碼
package com.jay; import org.apache.hadoop.hive.ql.exec.UDF; //自定義UDF函數 public class Myudf extends UDF{ //單個參數處理 public String evaluate(String value){ return value+"xxx";} //多參數處理 public String evaluate(String value1,int value2 ){ return value1+"-"+value2;} }
建立項目,導入hive的jar包,建立java類繼承org.apache.hadoop.hive.ql.exec.UDAF
建立靜態內部類,實現org.apache.hadoop.hive.ql.exec.UDAFEvaluator
重寫init方法,該方法至執行一次
boolean iterate(Object) 迭代器
Object terminatePartial() 臨時結果輸出
boolean merge(Object) 執行合併操做
Object terminate() 最終結果輸出
調用說明(根據需求調用以上方法)
map過程調用iterate與terminatePartial;
combiner(map合併)調用merge和terminatePartial
reduce調用merge與terminate
其餘步驟與HDF相同,調用UDAF會執行MR
import org.apache.hadoop.hive.ql.exec.UDAF; import org.apache.hadoop.hive.ql.exec.UDAFEvaluator; public class Myudaf extends UDAF{ public static class aaa implements UDAFEvaluator{ //定義一箇中間量,執行所需業務 private int sum; @Override public void init() { System.out.print("初始化,只執行一次"); } //迭代處理原始數據 public boolean iterate(String value) { if (value != null) sum += value.length(); return true; } //臨時輸出 public int terminatePartial() { return sum;} //合併 public boolean merge(int tmpSum) { sum += tmpSum; return true;} //最終輸出 public String terminate() { return "sum:" + sum;} } }
在優化中主要關注
Map的數量,reduce數量,文件數量,切片大小
hive中修改配置屬性語句爲:set xxx=值;
錶鏈接
select u.name, o.orderid from order o join user u on o.uid = u.uid
注:uid做爲key進行MR
表分組及分組函數
select rank, isonline, count (*) from city group by rank , isonline
注:將rank -isonline做爲key
表分組去重
select dealid, count(distinct uid) num from order group by dealid
注:根據dealid執行map以後的分區,根據分區的dealid+去重的uid執行reduce的分組
表多重去重
select dealid, count(distinct uid), count(distinct date) from order group by dealid
方式1:只能在reduce中去重
方式2:實如今map中去重
指定大表和小表。減小了全錶鏈接的數量
執行過程:小表節點先執行map,結果載入到hashtable中,各大表節點啓動map並將小表執行結果載入內存,在各大表節點執行map合併,再將數據寫出到reduce處理。
select * from a join b join c; 控制a<b<c,使得hive將a視爲b和c的小表,再將b視爲c的小表
select與where默認不會致使MR啓動
select * from t_emp where id = 8
若select中不須要分區和組函數,可使用hdfs默認的filter進行數據過濾
hive-site.xml中配置以下信息,屬性爲more時上述狀況默認不啓動MR
hive.fetch.task.conversion= more不啓動/minimal啓動
insert語句必然執行MR操做
map任務數量過多,節點容易oom(內存溢出)
map任務數量過少,任務節點少,處理速度慢
map數量與切片數量關聯,須要根據具體文件大小和內存設置map數
經過調整切片大小,能夠控制切出的切片數量,進而控制map數量
mapred.min.split.size 最小切片大小默認1B
mapred.max.split.size 最大切片大小默認256MB
上述值用B單位的數字進行設置
數量影響
reduce過多產生大量小文件,影響hdfs性能,增長NameNode的負擔
reduce過少,單節點壓力大容易oom
系統分配reduce方式,基於如下兩個參數設置
hive.exec.reducers.bytes.per.reducer 每一個reduce處理的數據量,默認1G
hive.exec.reducers.max 最大reduce數,默認999
set mapred.reduce.tasks直接設置reduce個數
系統也會依據桶的數量分配reduce數,使得數據可以存入分桶文件中
只有開啓一個reduce的狀況
分組函數沒有設置分區
select pt,count(1) from t_data where pt = ‘2012-07’ [group by pt];
使用 order by 排序
order by 會致使整表排序,只能由一個reduce處理
sorted by則只是對每一個reduce結果排序
行式數據庫:塊內存儲多行數據,一行中有多個不一樣的數據類型,查詢時須要依次進行解析全表數據
列式數據庫:塊內存列的數據,數據按列進行壓縮,因爲列屬性相同,壓縮與解析的格式相同,數據按列處理(列查詢效率高)
1,admin,123456 2,zhangsan,123456 3,lisi,123456 //行式壓縮 1,admin,123456;2,zhangsan,123456;3,lisi,123456 //列式壓縮 1,2 admin,zhangsan 123456,123456 3,lisi,123456 select id ,name from table; 適用於列存儲,使用較多 select * from table where id = 2; 適用於行存儲,大數據中使用較少
根據查詢高頻詞建立分區表,減小查詢時數據掃描的範圍
減小使用去重distinct,避免產生數據傾斜
JVM重用可使得JVM實例在同一個job中時候使用N次,減小內存開銷