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次,减小内存开销