表
内部表
内部表是未被 “external” 修饰的表,其由 hive 管理。内部表由于存储了元数据以及存储数据,所以删除内部表,存储数据与元数据也会被删除。并且内部表被创建得路径在 hive 的默认仓库目录,即 “ /user/Hive/warehouse/”
create external table student06(
id int,
name string,
age int) row format delimited fields terminated by '\t';
外部表
外部表是被 “external” 修饰的表,其由 HDFS 管理。删除外部表仅仅会删除元数据,但是存储数据不会被删除。用户在创建外部表时,可以自己指定表的路径:
create external table student06(
id int,
name string,
age int)
location '/dblocation02';
内、外部表总结
内部表 | 外部表 |
---|---|
目录由 hive创建在默认的目录下 | 目录由用户自己创建表时自己用 location 来指定 |
删除表时,表的元数据与表的数据目录都会被删除 | 删除表时,只删除表的元数据而表的数据不会被删除 |
一般来源的数据会在不同的平台上进行处理,所以为了方便映射,就可以采用 外部表来进行映射,这样即使删除掉了表,也不会删除数据。也就不会影响数据在其他平台上的处理了。
分区表
分区表是在系统下创建文件夹目录,把分类数据放在不同的目录里面,可以加快查询速度。
如: 创建一个以 age 分区的表,
create table student08(
num int,
name string
)PARTITIONED BY (age string) ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
//导入分区数据
LOAD DATA INPATH '/stud.txt' OVERWRITE INTO TABLE student08 PARTITION (age='7');
// 增加表分区
alter table student08 add partition(age='9') partition(age='15');
// 查看表分区
show partition tableName;
// 导入分区数据
insert into student08 partition(age='11');
select * from student08 where age='9';
// 删除表分区 -- 子目录和数据都会被删除
alter table tableName drop partition(day='11');
分区表中,表目录里面有多个子目录。如果要针对不同时间,格式等要求创建表,那么可以创建分区表,没有必要创建多个表。
分区表的数据是存放在不同的子目录中,在查询的时候,既可以针对子目录进行扫描,也可以针对全表进行扫描。
创建分区表后,分区目录看不到子目录,只有在导入数据才可以看到。
数据的导入与导出
load
- 从本地导入
load data local inpath 'local_path' into table tb_name;
- 从 HDFS 导入
load data inpath 'hdfs_path' into table tb_name;
// overwrite: 覆盖, 用于临时表
load data inpath 'hdfs_path' overwrite into table tb_name;
两者的不同主要是本地导入,需要加 “local” 关键字,不加 “local”,就是 HDFS 的导入加载。
as 查询输出
- 将从 tb1 的查询结果保存到 tb 上
create table tb_name as select * from tbl_name;
create table tb as select * from tb1
insert into 追加,导出
- 将从 tb1 上查询的结果追加到 tb 上
insert into table tb_name select * from tb1_name;
- 将从 tb1 上查询的记过覆盖到 tb 上。注意:这里有一个 overwrite 关键字。
insert overwrite table tb_name select * from tb1_name;
- 将 tb 上查询到的数据导出到 hdfs 上
insert overwrite directory 'hdfs_path' select * from tb_name;
- 将 tb 上查询到的数据导出到本地上
insert overwrite [local] directory 'path' select * from tb_name; //导出到本地
insert overwrite [local] directory 'path' row format delimited fields terminated by '\t' select * from tb_name; //数据之间会有制表空格
insert overwrite directory '/bb' select * from student08;
insert overwrite local directory '/bb' select * from student08; // 导出到本地
location 导入
- 将指定的本地文件导入到外部表中,或者管理表中对数据的指定
dfs -put local_file_path hdfs_table_name;
eg:
dfs -put /opt/app/dep2.txt /user/hive/warehouse/dp.db/dept
hdfs -put local_path hdfs_path; // hdfs 提交文件
hdfs -get hdfs_path local_path; //导出到本地
hive -e //将输出重定向保存到本地文件
hive -f //将输出重定向保存到本地文件
import& export
export table tb_name to 'hdfs_path'; //将数据导出来, 必须是一个空目录
import table tb_name form 'hdfs_path'; //将数据导入到数据库
Sqoop
涉及到 sqoop,等待 sqoop 操作再写。
Hive 函数分析
COUNT, SUM, MIN, MAX, AVG
lag 和 lead 有三个参数,第一个参数为列名,第二个参数是偏移的 offset,第三个参数是c超出记录窗口时的默认值。
LEAD(col, n, DEAFAULT) //用于统计窗口内往上第 n 行值
select lead(age) over(order by name) from student02;
select lead(age,2,0) over(order by name) from student02;
LAG(col, n, DEAFULT) //用于统计窗口内往下第 n 行值.
select lag(age) over(order by name) from student02;
select lag(age,2,0) over(order by name) from student02;
常用 HQL
过滤: where / limit / distinct (唯一查询) / between and / is null / is not null / case when then
select * from tb_name where name = 'add';
select * from tb_name limit 10, 1 // (从10开始(但不包括10), 选取 1 个)—
selct * from tb_name limit limit 2 //(选取 2 个);
select distinct name from tb_name; //唯一的name取出
select * from tb_name where name between 'aaa' and 'bbb'
select * from tb_name where name is null;
select * from tb_name where name is not null;
select * , (case sex when 1 then 'man' when 2 then 'women' else '' end) from tb_name;
select *, (case name when 'zhang01' then 'xxxx' when 'zhang02' then 'zzzz' else '' end) from student02;
聚合: count / sum / avg / max / min / group by / having //(必须有 group by)
select avg(col1 * col2) from tb_name;
select sum(col1) from tb_name;
select count(*) from tb_name where col1 >100;
select min(col1 * col2) from tb_name;
select max(col1 * col2) from tb_name;
select * from tb_name group by col_name;
select name,num,collect_set(age) from student02 group by name;
//SELECT student_class,COUNT(ALL student_name) AS 总人数 FROM t_student GROUP BY (student_class);
//select * from tb_name having col1 >20
select age, collect_set(name,num) from student02 group by age having age > 8;
//SELECT student_class,AVG(student_age) AS 平均年龄 FROM t_student GROUP BY (student_class) HAVING AVG(student_age)>20;
多表之间 inner join / 多表之间 left join / 多表之间 right join / 多表之间 full join
select * from tb1_name inner join tb2_name on tb1.colname = tb2.colname; //两表的交集.
// LEFT JOIN产生表1的完全集,而2表中匹配的则有值,没有匹配的则以null值取代。
select colname(s) form tb1_name left join tb2_name on tb1.colname = tb2.colname;
// RIGHT JOIN产生表2的完全集,而1表中匹配的则有值,没有匹配的则以null值取代
select colname(s) form tb1_name right join tb2_name on tb1.colname = tb2.colname;
//FULL OUTER JOIN产生1和2的并集。但是需要注意的是,对于没有匹配的记录,则会以null做为值
select colname(s) form tb1_name full join tb2_name on tb1.colname = tb2.colname;
// 导入
load data local inpath '/a1.txt' into table student08 partition (age='11');
load data local inpath '/a1.txt' overwrite into table student08 partition (age='15'); // 覆盖
load data inpath '/a.txt' into table student08; // 从 hdfs 上的 a.txt 导入
HQL 执行顺序
– 第一步:执行 FROM
– 第二步:WHERE 条件过滤
– 第三步:GROUP BY 分组
– 第四步:执行 SELECT 投影列
– 第五步:HAVING 条件过滤
– 第六步:执行 ORDER BY 排序
Hive 运行参数
// 设置每个 reduce 处理的数据量hive.exec.reducers.bytes.per.reduce=
// 设置最大能够运行的 reduce 个数
hive.exec.reducer.max=
// 实际 reduce 的个数
mapreduce.job.reduces=
// 设置 reduce 开启条件
hive.fetch.task.conversion=fertchtask / mapreduce
排序方式
- order by 全局排序
order by 会对查询的全局结果进行排序。最终 map 数据的数据汇聚到一个 reduce 中去执行。如果数据量很大,那么这个操作是相当漫长的。所以在 hive 操作中尽量少用 order by,除非数据量很小。
select * from student08 order by age;
- sort by 局部排序
sort by 是一个局部排序,也就是说在每个 reduce 中进行排序,保证每个reduce 中的数据是有序的。但是对于全局而言,其又不一定是有序的。
select * from student08 sort by age;
- distribute by 分区
distribute by 是指定输出结果怎样划分到各自的 reduce 分区中。
eg:指定 age 字段相同的结果被划分到同一个 reduce分区中。
select * from student08 distribute by age;
- cluster by = sort by + distribute by
cluster by 具有 sort by 与 distribute by 的两重功能。能将相同字段进行 sort by 排序和distribute by 分区。
select * from student08 cluster by age;
select * from student08 distribute by age sort by age;
自定义函数 UDF
- 配置环境 pom / hive-site.xml
- 自定义类继承 org.apache.hadoop.hive.ql.exec.UDF
定义 public Object evaluate(Object args) 方法 - 导出 jar 包并植入本地环境 linux 的 localpath 目录下
- 关联 jar, 进入hive add jar localpath;
- 创建临时函数 create temperary function 函数名 as ‘包名.类名’;
- 执行
public class UserInfoParser extends UDF{
public String evaluate(String field,int index){
String replaceAll = field.replaceAll("\\|", " ");
String[] split = replaceAll.split(" ");
return split[index-1];
}
}
// 创建临时函数
create temporary function functionName as 'packageName.className';
虚拟列
虚拟列并不是在表中真正存在的列,其用意是为了将 hive 中的表进行分区,这对每日增长的海量数据存储而言非常有用的。
其种类有两种:
- 这行数据属于哪个文件 ---- INPUT__FILE__NAME
- 块的偏移量,类似于每行的存储地址 ---- BLOCK__OFFSET__INSIDE__FILE
select *, INPUT__FILE__NAME from student;
select *, BLOCK__OFFSET__INSIDE__FILE from student;