设置属性:
//设置本地执行作
set hive.exec.mode.local.auto=true;
//设置动态分区
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nostrict;
//设置reduce task数量
set mapred.reduce.tasks=2;
//对mapjoin优化设置
set hive.auto.convert.join=true;
创建表:
//创建内部表
create table 表名(
字段1 类型,
字段2 类型,
... ...)
row format delimited
fields terminated by'\t';
//创建外部表
create external 表名(
字段1 类型,
字段2 类型,
... ...)
row format delimited
fields terminated by','
location '/external';
在导入数据的过程中,如果在建表的过程中没有指定location,那么就会在hive-site.xml配置的hive.metastore.warehouse.dir指定的路径下,
以表名创建一个文件夹,之后所有有关该表的数据都会存储到此文件夹中。
//创建分区表
create table 表名(
字段1 类型,
字段2 类型,
... ...)
partitioned by(分区的字段名 类型)
row format delimited
fields terminated by'\t';
//创建带桶的表
//Hive使用对值进行哈希并将结果除 以桶的个数取余数。
//要通过insert into/overwrite导入数据 ,跑了MapReduce ,hdfs才有分桶,通过load导入没有
create table 表名(
字段1 类型,
字段2 类型,
... ...)
clustered by(分桶的字段名) into 2 buckets
row format delimited
fields terminated by',';
//创建分区分桶的表
create table 表名(
字段1 类型,
字段2 类型,
... ...)
partitioned by(分区的字段名 类型)
clustered by(分桶的字段名) into 2 buckets
row format delimited
fields terminated by'\t';
修改表:
//增加分区
alter table 表名 add partition(分区字段名='新分区的值');
注意,新建的分区是没有数据的,我们可以往里面存储数据
//删除分区
alter table 表名 drop if exists partiton(分区字段名='分区的值');
//重命名表
alter table 原表名 rename to 新表名;
//增加一列或多列
alter table 表名 add columns(新字段1 类型,新字段2 类型,...)
//删除列replace 官网没有提供alter table drop的语句,该语句只对partiton去除有效
//假设表person有字段 id,name,age,address,phone 删掉address和phone
alter table person replace columns(id int,name String,age int);
//替换列(修改列名)replace
alter table t_modify replace columns(id int,name String,age2 int);
//修改列名和类型
alter table 表名 change 字段名 新字段名 原字段类型;
alter table aa change time1 time String;
修改字段类型只能从int修改为float或double,float修改为double。反过来则不行
//清空表数据,保留表结构
truncate table 表名;
//拷贝表结构
create table 表2 like 表1;
//存储表数据
create table 表2 as select * from 表1;
//分组查询
select collect_set(name),collect_set(age) from t_data group by time;
select collect_set(name),count(*) from t_data group by time;
注意:collect_set会去重,collect_list不会去重
显示命令:
//显示某数据库下的所有表
show tables;
//显示所有数据库
show databases;
//显示表的所有分区
show partitions 表名;
加载数据:
//加载绝对路径数据
load data local inpath '/home/dummy/data.log' into table t_partition partition(ds='20171113');
//加载相对路径数据
load data local inpath 'data.log' into table t_partition;
//加载HDFS数据(不加local即可)
load data inpath 'data.log' into table t_partition;
//插入数据1
insert into table t_partition partition(ds='20171113')
select * from t_data where t_data.time='20171113';
//插入数据2
insert into table 表名 (字段a,字段b,...) values(字段值1,段值2,...);
insert into table 表名 values(字段值1,段值2,...);
//多插入数据
from t_data
insert into t_partition partition(ds='20171113')
select * where time='20171113'
insert into t_partition partition(ds='20171114')
select * where time='20171114';
//动态分区插入数据,先设置动态分区,见开头
insert into table t_part_access_log partition(month)
select u.valid,u.ip,,u.day,u.times,u.month from
(select valid,ip,name,
split(time,'/')[0] day,
split(time,'/')[1] month,
split(time,'/')[2] times
from t_access_log)u;
导出数据:
//导出表数据到本地
insert overwrite local directory '/home/dummy/data_out.log'
select * from t_access_log where valid!='false';
或者
from t_access_log
insert overwrite local directory '/home/dummy/data_out.log'
select * where valid!='false';
//导出表数据到HDFS
insert overwrite directory '/data_out.log'
select * from t_access_log where valid!='false';
Hive join操作:
准备的数据源,表t_a
1 | a |
2 | b |
3 | c |
4 | d |
准备数据源,表t_b
1 | aa |
2 | bb |
3 | cc |
4 | dd |
5 | ee |
6 | ff |
内连接:内连接,也被称为自然连接,只有两个表相匹配的行才能在结果集中出现。返回的结果集选取了两个表中所有相匹配的数据,
舍弃了不匹配的数据。由于内连接是从结果表中删除与其他连接表中没有匹配的所有行,所以内连接可能会造成信息的丢失
select a.*,b.* from t_a a join t_b b on =;
结果:
1 a 1 aa
2 b 2 bb
3 c 3 cc
4 d 4 dd
外连接:外连接不仅包含符合连接条件的行,还包含左表(左连接时)、右表(右连接时)或两个边接表(全外连接)中的所有数据行。
left outer:
select a.*,b.* from t_a a left join t_b b on =;或者
select a.*,b.* from t_a a left outer join t_b b on =;
结果:
1 a 1 aa
2 b 2 bb
3 c 3 cc
4 d 4 dd
right outer:
select a.*,b.* from t_a a right outer join t_b b on =;
结果:
1 a 1 aa
2 b 2 bb
3 c 3 cc
4 d 4 dd
NULL NULL 5 ee
NULL NULL 6 ff
full outer:
select a.*,b.* from t_a a full outer join t_b b on =;
结果:
1 a 1 aa
2 b 2 bb
3 c 3 cc
4 d 4 dd
NULL NULL 5 ee
NULL NULL 6 ff
left semi:
select a.* from t_a a left semi join t_b b on =;
结果:
1 a
2 b
3 c
4 d
写
1. 等值join
SELECT a.* FROM a JOIN b ON (>) 是错误的!
但是你给出具体的值是可以的,笛卡尔积操作
hive> select a.*,b.* from t_a a join t_b b on >3;
等效于
select a.*,b.* from t_a a ,t_b b where >3;
结果:
4 d 1 aa
4 d 2 bb
4 d 3 cc
4 d 4 dd
4 d 5 ee
4 d 6 ff
不等值查询,
select a.*,b.* from t_a a ,t_b b where >;
结果:
2 b 1 aa
3 c 1 aa
4 d 1 aa
3 c 2 bb
4 d 2 bb
4 d 3 cc
2. 可以
例如
如果join中多个表的 join key 不是同一个,则 join 会被转化为2个 map/reduce 任务,
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2);
如果join中多个表的 join key 是同一个,则 join 会被转化为单个 map/reduce 任务,
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
3.join 时,每次 map/reduce 任务的逻辑:(小表join大表)
reducer 会缓存 join 序列中除了最后一个表的所有表的记录,再通过最后一个表将结果序列化到文件系统。
这一实现有助于在 reduce 端减少内存的使用量。实践中,应该把最大的那个表写在最后(否则会因为缓存浪费大量内存)。
例如:
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
所有表都使用同一个
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
这里用了
这里必须设置join优化
set hive.auto.convert.join=true;
4.LEFT,RIGHT 和 FULL OUTER 关键字用于处理 join 中空记录的情况
例如:
SELECT a.val, b.val FROM
a LEFT OUTER JOIN b ON (a.key=b.key)
对应所有
a.val, NULL
所以
“a RIGHT OUTER JOIN b”会保留所有 b 表的记录。
Join 发生在 WHERE 子句之前。如果你想限制
SELECT a.val, b.val FROM a
LEFT OUTER JOIN b ON (a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
会 join a 表到 b 表(OUTER JOIN),列出 a.val 和 b.val 的记录。WHERE 从句中可以使用其他列作为过滤条件。但是,如前所述,如果 b 表中找不到对应 a 表的记录,b 表的所有列都会列出 NULL,包括。也就是说,join 会过滤 b 表中不能找到匹配 a 表 join key 的所有记录。这样的话,LEFT OUTER 就使得查询结果与 WHERE 子句无关了。解决的办法是在 OUTER JOIN 时使用以下语法:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON (a.key=b.key AND
b.ds='2009-07-07' AND
a.ds='2009-07-07')
这一查询的结果是预先在
Join 是不能交换位置的。无论是
SELECT a.val1, a.val2, b.val, c.val
FROM a
JOIN b ON (a.key = b.key)
LEFT OUTER JOIN c ON (a.key = c.key)
先