第一步:输入一条HQL查询语句(eg. select * from tab)
第二步:解析器对这条Hql语句进行语法分析。
第三步:编译器对这条Hql语句生成HQL的执行计划。
第四步:优化器生成最佳的Hql的执行计划。
第五步:执行这条最佳Hql语句。
create database mydb;
create database if no exists mydb;
create database if no exists mydb location "/aa/bb";
查询库列表:show databases;
查询库详细信息:desc database [extended] mydb;
查询建库的详细信息:show create database mydb;
drop database mydb;
drop database if exists mydb;
drop database if exists mydb [restrict|cascade];
use mydb;
show tables;
show tables in mydb;
create table mingxing_mng(id int, name string, sex string, age int, department string) row format delimited fields terminated by ',';
show create table mingxing;
create external table mingxing_ext(id int, name string, sex string, age int, department string) row format delimited fields terminated by ',' location '/home/hadoop/hivedata';
注意:创建外部表的时候指定location的位置必须是目录,不能是单个文件
1、外部表在创建表的时候指定关键字: external,需要指定一个外部路径
(内部表也可以指定数据存储目录)
2、在导入数据到外部表,数据并没有移动到自己的数据仓库目录下,也就是说外部表中的数据并不是由hive自己来管理的!
3、在删除表的时候,Hive将会把属于表的元数据和数据全部删掉;而删除外部表的时候,Hive仅仅删除外部表的元数据,数据是不会删除的,外部表的原始数据一般存储在本地数据库中!
4、应用场景不同:内部表一般存放中间结果数据、内部数据、或者由外部表生成的报表数据;外部表一般存放一些共享数据(公共数据)、原始采集的数据。
在表目录中为数据文件创建分区子目录,以便于在查询时MR程序可以针对指定的分区子目录中的数据进行处理,缩减读取数据的范围,提高效率!
语法:
create table mingxing_ptn(id int, name string, sex string, age int, department string) partitioned by (city string) row format delimited fields terminated by ‘,’;
注意:partitioned里的字段不是能是表中声明的字段,必须是一个新字段
create table mingxing_ptn(id int, name string, sex string, age int, department string) partitioned by (province string,city string) row format delimited fields terminated by ',';
create table t_sale_pt2 like t_sale_pt1;
方式一:create table t_amt as select shop,sale from t_sale;
方式二:如果事先已存在一张表t_x,可以将查询的结果insert到已存在的表中
insert into t_x select …
hive支持多种格式的文件,如text file,sequencefile,parquetfile等
create table mingxing_ptn(id int, name string) stored as sequencefile;
create table mingxing_bck(id int, name string, sex string, age int, department string) clustered by(id) sorted by(age desc) into 4 buckets row format delimited fields terminated by ',';
注意:clustered里的字段必须要是表字段中出现的字段
分桶字段 表字段
分桶字段和排序字段可以不一样,分桶字段和排序字段都必须是表字段中的一部分
分桶的原理和MapReduce的HashPartitioner的原理一致
分区在HDFS上的表现形式是一个目录, 分桶是一个单独的文件
分区: 细化数据管理,直接读对应目录,缩小mapreduce程序要扫描的数据量
分桶: 1、提高join查询的效率(用分桶字段做连接字段)
2、提高采样的效率
drop table mingxing;
drop table if exists mingxing;
alter table mingxing rename to student;
alter table mingxing add columns (province string);
alter table mingxing add columns (province string, salary bigint);
drop(不支持) XXXXX
alter table mingxing change age newage string; // 修改字段的定义
alter table mingxing change age newage string after id; // 修改字段的定义 + 顺序
alter table mingxing change age newage string first; // 修改age字段为第一个字段
alter table mingxing replace columns(id int, name string, sex string); // 替换所有字段
alter table mingxing_ptn add partition(city='beijing');
alter table mingxing_ptn add partition(city='beijing') partition(city='tianjin');
二级分区:
alter table mingxing_ptn add partition(city='beijing', email="[email protected]");
alter table mingxing_ptn add partition(city='beijing', email="[email protected]") partition(city='tianjin', email="[email protected]");
alter table mingxing_ptn drop partition(city='beijing');
alter table mingxing_ptn drop partition(city='beijing'), partition(city='tianjin');
alter table mingxing_ptn add partition(city='beijing', email="[email protected]");
alter table mingxing_ptn add partition(city='beijing', email="[email protected]"), partition(city='tianjin', email="[email protected]");
修改分区路径:
alter table mingxing_ptn partition(city="beijing") set location "/mingxing_beijing";
select * from mingxing_ptn where city=‘beijing’;
分区被看作是原表的一个字段
查询二级分区数据:
select * from mingxing_ptn where province=‘shaanxi’ and city=‘xian’;
查看库:show databases;
查看表:show tables;
查看建表完整语法:show create table mingxing_mng;
查看内置函数库:show functions;
查看函数的详细手册:desc function extended concat;
查看分区:show partitions mingxing_ptn;
查看表的字段:desc mingxing_mng;
查看表的详细信息:desc extended mingxing_mng;
查看表的格式化了之后的详细信息:desc formatted mingxing_mng;
load data local inpath './student.txt' into table mingxing;
load data local inpath './student.txt' overwrite into table mingxing;(覆盖导入)
load data local inpath '/home/hadoop/hivedata/student.txt' into table mingxing;
load data inpath '/home/hadoop/hivedata/student.txt' into table mingxing;
load data inpath 'hdfs://hadoop01:9000/home/hadoop/hivedata/student.txt' into table mingxing;
load data local inpath ‘/root/jd.2018-01-01’ into table t_sale partition(day=‘20180101’);
load data local inpath ‘/root/jd.2018-01-01’ into table t_sale partition(month=‘201801’,day=‘20180101’);
load data local inpath ‘/root/jd.2018-01-02’ into table t_sale partition(month=‘201801’,day=‘20180102’);
1、导入HDFS上的数据到hive表,表示剪切,移动
2、导入本地数据,相当于复制或者上传
insert into table mingxing values(001,'huangbo','male',50,'MA');
insert into table student select id,name,sex,age,department from mingxing;
注意:查询出的字段必须是student表中存在的字段
from mingxing
insert into table student1 select id,name,sex,age
insert into table student2 select id,department;
from mingxing2
insert into table student1 partition(department='MA') select id,name,sex ,age where department='MA'
insert into table student1 partition(department='CS') select id,name,sex ,age where department='CS';
需要手动的创建分区
alter table student add partition (city="zhengzhou")
load data local inpath '/root/hivedata/student.txt' into table student partition(city='zhengzhou');
打开动态分区的开关:set hive.exec.dynamic.partition = true;
设置动态分区插入模式:set hive.exec.dynamic.partition.mode = nonstrict
create table student(name string, department string) partitioned by (id int) .....
insert into table student partition(id) select name,department,id from mingxing2;
查询字段是:name,department,id,分区字段是id
注意:动态分区插入的分区字段必须是查询语句当中出现的字段中的最后一个
CTAS(create table ... as select ...)(直接把查询出来的结果存储到新建的一张表里)
create table student as select id,name,age,department from mingxing;
注意:自动新建的表中的字段和查询语句出现的字段的名称,类型,注释一模一样
限制:
1、不能创建外部表
2、不能创建分区表
3、不能创建分桶表
1)静态分区加载数据的时候是需要手动静态指定分区名字和值,并配合where使用
动态分区数据加载的时候会根据查询分区字段进行动态生成分区的
2)对于静态分区来说存在某一个分区数据为空的情况
动态分区每一个分区都不存在数据为空的情况 每一个分区至少有1条分区
3)动态分区在进行数据加载的时候并行加载的
每一个分区这里都会对应多个maptask任务 消耗性能的
数据加载:
(1)静态:
insert into table stu_ptn_sex_d partition(sex="男",age=18) select id,name,dept from stu_managed where sex='男' and age=18;
存储路径:/user/hadoop/hive/bd1809.db/stu_ptn_sex_d/sex=男/age=18
(2)动态:
insert into table stu_ptn_sex_d partition(sex,age) select id,name,dept,sex,age from stu_managed;
(3)有静态 还有动态
静态必须为高级的 动态--低级的
insert into table stu_ptn_sex_d partition(sex="unkown",age)
select id,name,dept,age from stu_managed where sex='unkown';
create table mingxing(id int, name string, sex string, age int, department string)
clustered by(id) sorted by(age desc) into 4 buckets
row format delimited fields terminated by ',';
insert into table mingxing select id,name,sex,age,department from mingxing2
distribute by id sort by age desc;
注意:查询语句中的分桶信息必须和分桶表中的信息一致
insert overwrite directory ‘/root/access-data’ row format delimited fields terminated by ‘,’ select * from t_access;
insert overwrite local directory ‘/root/access-data’ row format delimited fields terminated by ‘,’ select * from t_access;
单模式导出数据到本地:
insert overwrite local directory '/root/outputdata' select id,name,sex,age,department from mingxing;
多模式导出数据到本地:
from mingxing
insert overwrite local directory '/root/outputdata1' select id, name
insert overwrite local directory '/root/outputdata2' select id, name,age
简便路径模式导出到hdfs:
insert overwrite directory '/root/outputdata' select id,name,sex,age,department from mingxing;
全路径模式查询数据到hdfs:
insert overwrite directory 'hdfs://hadoop01:9000/root/outputdata1' select id,name,sex,age,department from mingxing;
local :导出到本地目录
overwrite :表示覆盖
truncate table mingxing2;
order by : 全局排序
如果一个HQL语句当中设置了order by,那么最终在HQL语句执行过程中设置的
只有一个Reducer,输入规模较大时,消耗较长的计算时间
此时,set mapreduce.job.reduces = 4 不起作用。!!
sort by :局部排序
一般来说,要搭配 分桶操作使用,只会保证每个reducer的输出有序
distribute by id sort by age desc;
distribute by : 纯粹就是分区,默认是采用hash算法
在使用distribute by的时候:要设置reduceTask的个数
cluster by : 既分区,也排序,但只能升序,不能指定排序规则。
cluster by age = distribute by age sort by age;
distribute by age sort by age,id != cluster by age sort by id
cluster by 和 sort by 不能同时使用
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
select a.* from a left join b on a.id=b.id where b.id is null;
经验:
当出现多个表进行连接时,最好把小表放置在前面!! 把大表放置在最后
join分类;
inner join
left outer join
right outer join
full outer join
left semi join,它是in、exists的高效实现
select a.* from a left semi join b on a.id = b.id
等价于:
select a.* from a where a.id in (select b.id from b);#不建议使用
创建表:
CREATE TABLE student(
name STRING,
favors ARRAY,
scores MAP,
address STRUCT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ';' #指定多个属性之间的分隔符
MAP KEYS TERMINATED BY ':' ; #指定map集合中k-v的分隔符
导入数据:
load data local inpath '/home/hadoop/student.txt' into table student;
查询:
select name,favors[1] ,scores["yuwen"], address.province from student;
创建视图
create view view_name as select * from carss;
create view carss_view as select * from carss limit 500;
查看视图
show tables; // 可以查看表,也可以查看视图
desc view_name // 查看某个具体视图的信息
desc carss_view
删除视图
drop view view_name
drop view if exists carss_view
使用视图
create view sogou_view as select * from sogou_table where rank > 3 ;
select count(distinct uid) from sogou_view
查看内置函数:
show functions;
显示函数的详细信息:
desc function abs;
显示函数的扩展信息:
desc function extended concat
数值操作:
ceil 向上取整
floor 向下取整
rand 生成随机数
rand([seed]) - Returns a pseudorandom number between 0 and 1
使用无参的 生成0-1之间的一个随机数
参数:随机数种子
round:
round(x[, d]) - round x to d decimal places,指定保留小数
传一个参数 对这个参数取整 四舍五入
传2个参数,参数2代表的是保留小数的个数
select round(rand(),2); 随机数保留两位小数
字符串操作:
split
split(str, regex)
参数1 被分割的字符串 参数2 分割符,返回值 : 数组
substr
substring
字符串截取
substr(str, pos[, len]) 字符串下标从1开始的
两边索引 左侧从1开始 右侧从-1开始
参数1 原始字符串 参数2 起始位置(包含) 参数3 截取长度
trim 前后空格 trim(str)
ltrim 去左侧空格
rtrim 去右侧空格
去字符串的空格的
instr 字符串查找
instr(str, substr)
参数1 原始字符串 参数2:需要查找的自符串
存在:返回的是子字符串的第一个字符的所在的位置
不存在:0
concat
concat_ws
定分割符进行字符串拼接
concat(str1, str2, ... strN) 将参数进行顺序拼接,拼接的时候没有分割符的
concat_ws(separator, [string | array(string)]+)
参数1 分割符 参数2:需要进行拼接的字符串组|字符串的数组
lcase小写
lower小写
ucase大写
upper大写
replace(str, search, rep)字符串替换
参数1 原始字符串 参数2 需要替换的 参数3 替换的值
集合操作:
array
array(n0, n1...)
将多个参数转换为数组
hive> select array(1,2,3,4,"hello");
["1","2","3","4","hello"]
array_contains:
array_contains(数组, 判断的值) 返回值boolean 存在true 不存在 false
map:
生成map的函数 k-v
map(key0, value0, key1, value1...) 参数个数必须偶数个
奇数位--key 偶数位---value
map_keys
map_values
参数 map
分别返回map的key和value值的数组
collect_set:去重收集函数
collect_list:不去重收集函数
以上两个都是多行并一行的操作,也叫收集函数 将多行数据某一个字段进行收集 收集到一个集合中 返回的是一个数组
在进行收集的时候可以借助group by进行分组收集
案例:
每个部门中的年龄分布
select dept,collect_set(age) from stu_managed group by dept;
按照分组字段返回的
CS [21,19,20,23,18]
IS [19,18,21,79]
MA [22,18,19,17,20]
如果没有使用分组 全表收集的 最终返回一个大的数组;
类型转换函数:
cast(原始数据 as 需要转换的类型)
select cast("123 " as int);
select if(scores[2] is null,0,scores[2]) from test_array;
nvl(value,default_value)
如果第一个参数为null则返回第二个参数 第一个参数不为null直接返回参数1
select nvl(scores[2],0) from test_array;
语法1:(用于精确匹配)
case 用于判断的字段
when 值1 then 满足条件的返回值
when 值2 then 满足这个条件的返回值
else 其他情况的返回值 end
select case dept when "IS" then 1 when "CS" then 2 when "MA" then 3 end deptid from stu_managed;
语法2:
case
when 条件1 then 满足条件1的返回值
when 条件2 then 满足条件2的返回值
else 其他情况的返回值 end
select
case when age>=20 then 1 else 0 end
from stu_managed;
一行经过炸裂之后成为多行
explode(a):要求参数a必须为array或map
当参数为array时:
select id,stc.* from test_map lateral view explode(scores) stc;
当参数为map时:
select id,stc.mv from test_map lateral view explode(scores) stc as mk,mv;
说明:
1)lateral view explode(scores) stc:将explode的炸裂结果存储为一个视图 并给视图命名stc
2)如果需要视图中的某一个字段 需要为字段重命名的,使用as关键字 为字段起别名
over子句:用于指定分组(分区)或排序规则的 行号|排名规则
over子句中的语法
over(distribute by + sort by )
over(partition by + order by )
select * from
(select dept,name,age,row_number() over(distribute by dept sort by age desc) index
from stu_managed) a
where index<=2;
rank:会累加并列
select dept,name,age,rank() over(partition by dept order by age)
from stu_managed;
结果:
CS 李娜 18 1
CS 李娜 18 1
CS 王小丽 19 3
CS 孔小涛 19 3
CS 孔小涛 19 3
CS 王小丽 19 3
CS 孙花 20 7
dense_rank:不会累加并列
select dept,name,age,dense_rank() over(partition by dept order by age)
from stu_managed;
结果:
CS 李娜 18 1
CS 李娜 18 1
CS 王小丽 19 2
CS 孔小涛 19 2
CS 孔小涛 19 2
CS 王小丽 19 2
CS 孙花 20 3
CS 李勇 20 3
UDF(用户定义函数user-defined function)作用于单个数据行,产生一个数据行作为输出。(数学函数,字符串函数)
UDAF(用户定义聚集函数 User- Defined Aggregation Funcation):接收多个输入数据行,并产生一个输出数据行。(count,max)
UDTF(用户定义表生成函数 User-Defined Table Functions):接收一行输入,输出多行(explode)
UDF 示例:
1)创建工程 导包 添加hive的安装目录下的lib下的依赖
2)创建 java 类,继承 org.apache.hadoop.hive.ql.exec.UDF,重载 evaluate 方法,参数 和返回值 一定确定好
import org.apache.hadoop.hive.ql.exec.UDF;
public class ToLowerCase extends UDF {
// 必须是 public,并且 evaluate 方法可以重载
public String evaluate(String field) {
String result = field.toLowerCase();
return result;
}
}
4)将工程打成jar包 传到hive所在节点的服务器上
5)将jar包放在hive的classpath
add jar /home/hadoop/data_hive/myudf.jar;
验证:list jars;
6)创建一个函数 关联 jar包中的类
创建一个临时函数
create temporary function funname as ‘自己定义的UDF类的全限定名’;
create temporary function myfun 'com.ghgj.hive.udf.ToLowerCase';
验证:
show functions;
7)使用
select myfun(name),age from student;
用于解析json字符串的
是对象|map + 数组 的数据组织形式
{}:对象(map)
[]:数组
样例数据:
[{"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"}]
{
"name": "BeJson",
"url": "http://www.bejson.com",
"page": 88,
"isNonProfit": true,
"address": {
"street": "科技园路.",
"city": "江苏苏州",
"country": "中国"
},
"links": [
{
"name": "Google", $.links[0].name
"url": "http://www.google.com"
},
{
"name": "Baidu",
"url": "http://www.baidu.com"
},
{
"name": "SoSo",
"url": "http://www.SoSo.com"
}
]
}
解析:
1.建表并加载数据
建表只需要指定一个字段
create table test_json(line string);
load data local inpath '/home/hadoop/data_hive/json' into table test_json;
2.json格式的解析
get_json_object:用于解析json的
get_json_object(json_txt, path)
参数1:json格式的字符串
参数2:需要解析的属性在json串中位置
$ : json串的根目录 json的最外层的结构
. : 取子节点 取对应属性的
[] : 去取数组中的元素 中括号中放的是数组下标 0开始
* : 所有
解析test_json表:
create table json_final as
select
get_json_object(line,'$.movie') movie,
get_json_object(line,'$.rate') rate,
get_json_object(line,'$.timeStamp') time01,
get_json_object(line,'$.uid') uid
from test_json;
注意:
get_json_object 最终解析的数据类型都是string
hive中默认的分割符的解析方式:
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
这种解析分割符的方式 只能解析单字节分割符 不能解析多字节分隔符:
现有数据样例:
3939::Slumber Party Massacre II, The (1987)::Horror
解决方案:
1)将多字节分割符替换为单字节分隔符 一定要足够的保证原始的字段中的数据不包含你最终转换的单字节
2)自己在建表语句中定义输入和输出
输入:可以具备代表性 根据数据自动匹配 正则表达式
输出:取正则表达式中符合规则的数据
语法规则:
create table movie02(movieid int,title string,type string)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties('input.regex'='(.*)::(.*)::(.*)','output.format.string'='%1$s %2$s %3$s')
stored as textfile;
serde:分割方式解析类 需要使用正则表达式的解析
with serdeproperties 指定的是分割属性 输入和输出的自定义
input.regex 输入的正则表达式
output.format.string 输出结果
输入正则表达式:
3939::Slumber Party Massacre II, The (1987)::Horror
(.):.):.*)
() 用于分组 分组目的:作为一个整体
从最左测开始 编组号 从1 开始 顺序递增的
输出:直接取每一组数据就可以
$s 占位符
加载数据:
load data local inpath '/home/hadoop/data_hive/movie' into table movie02;