1.Hive基本概念
1.1 数据仓库1.1 什么是hive?1.2 hive 架构?1.3 hive 和数据库对比 2.hive 数据类型
2.1 基础数据类型2.2 复杂数据类型2.3 类型转换 3.DDL 定义
3.1 创建数据库3.2 查询数据库3.3修改数据库3.4 删除 4. 创建表
4.1 hive 表的映射关系4.1内部表:管理表4.2 外部表4.3 修改表4.4 删除表4.5 清空表4.6分区表4.7 分桶表 5.DML
5.1 数据导入规则5.2 数据导出规则5.3 查询
5.3.1 别名5.3.2 Like 和 RLike5.3.3 groupby5.3.4having 与 where 不同点5.3.5 内连接和外连接5.3.6 union和unionall5.3.7 多表查询5.3.8hive排序:
5.3.8.1 全局排序5.3.8.2 sort by 局部排序!5.3.8.3 distribute by 分区排序5.3.8.4 cluster by 分桶排序
1.Hive基本概念 1.1 数据仓库数据仓库(Data Warehouse)是一个面向主题的、集成的
相对稳定的(Non-Volatile)、相对稳定的(Non-Volatile)、反映历史变化。
面向主题:按主题来进行组织(多张事实表 + 多张维度表)
集成的(Integrated):把数据按照主题的方式,放置在一个数据仓库。
相对稳定的:基本不会改变的,没有update和delete的需求
反映历史变化:每一条记录都是表示过去某个时刻的一条事实。
数据仓库的价值:用于支持管理决策。
Hive依赖于HDFS存储数据,Hive将HQL转换成MapReduce执行,所以说Hive是基于Hadoop的一个数据仓库工具
Hive 本质:将 HQL 转化成 MapReduce 程序。
sql->mapreduce
客户端->sql->(本身里面有sql映射mapreduce的模版)->将sql匹配出对应的mapreduce模版执行mapreduce.
sql->mapreducer
Driver接受客户端的sql语句,将compiler将sql编译成sql抽象语法树(抽象语法树进行变换)。optimizer变成逻辑执行计划,优化之后变成物理计划。物理执行计划在通过executor提交到hadoop集群中运行。
Hive的元数据:(把存储在HDFS上的结构化数据,想象成一张二维表格)
1、表名(表和数据文件之间的映射关系)
2、字段定义(由那些字段组成的)
3、行列分隔符(既然把文件想象成二维表格,那么行与行之间的界限,列与列的界限)
4、表中的数据(存储在HDFS上的文件,到底那张表对应到文件呢?)
1.查询语言:hive hql,mysql 是sql。
2.数据更新:hive 大多数是读多分析多,mysql 增删改多。
3.执行延迟。hive 表没有索引,所以会慢,mysql有索引。
4.数据规模:hive 是基于mapreduce 的大数据的计算,mysql 支持的数据量偏小。
隐式类型转换规则如下:
1)任何整数类型都可以隐式地转换为一个范围更广的类型,如 TINYINT 可以转换成INT, INT 可以转换成 BIGINT。
2)所有整数类型、 FLOAT 和 STRING 类型都可以隐式地转换成 DOUBLE。
3) TINYINT、 SMALLINT、 INT 都可以转换为 FLOAT。
4) BOOLEAN 类型不可以转换为任何其它的类型
显式类型转换规则如下:
Cast(字段名 as 转换的类型 )
select cast(date as datetime) as date from table1;3.DDL 定义 3.1 创建数据库
CREATE DATAbase [IF NOT EXISTS] database_name [COMMENT database_comment] [LOCATION hdfs_path] [WITH DBPROPERTIES (property_name=property_value, ...)]; --创建
create database db_hive;
创建一个数据库,数据库在 HDFS 上的默认存储是/user/hive/warehouse/*.db
--创建一个数据库并且指定存储地址 create database if not exists db_hive2 location '/db_hive/db'3.2 查询数据库
--显示数据库 show database; --过滤显示查询的数据库 show database like 'db_hive*'; --显示数据库的信息 desc database db_hive; --显示数据库的详细信息 extended desc database extended db_hive --切换数据库 use database(db_hive);3.3修改数据库
用户可以使用 ALTER DATAbase 命令为某个数据库的 DBPROPERTIES 设置键-值对属性值。
alter database db_hive set dbproperties('createtime'='20170830');
desc database extended db_hive;
3.4 删除
如果删除的数据库不存在, 最好采用 if exists 判断数据库是否存在。
drop database if exists db_hive2;
如果数据库不为空,可以采用 cascade 命令,强制删除。
drop database db_hive cascade;4. 创建表
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] [TBLPROPERTIES (property_name=property_value, ...)] [AS select_statement] 解释: 1.EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时可以指定一个指向实际数据的路径(LOCATION), 在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。(元数据是创建表的相关信息) 2. COMMENT:为表和列添加注释。 3.PARTITIonED BY 创建分区表 4. CLUSTERED BY 创建分桶表 5.SORTED BY 不常用,对桶中的一个或多个列另外排序 6. ROW FORMAT DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)] 7.STORED AS 指定存储文件类型 常用的存储文件类型: SEQUENCEFILE(二进制序列文件)、 TEXTFILE(文本)、 RCFILE(列式存储格式文件)如果文件数据是纯文本,可以使用STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。 8.LOCATION :指定表在 HDFS 上的存储位置 9.AS:后跟查询语句, 根据查询结果创建表4.1 hive 表的映射关系
数据仓库的默认路径:/user/hive/warehouse/ 库路径:nxde1.db 表路径:nx_student 数据文件:stduent.txt 当前表的数据存储目录的完整路径: /user/hive/warehouse/nxde1.db/nx_student/stduent.txt 映射关系: 表:nx_student HDFS目录:/user/hive/warehouse/nxde1.db/nx_student/4.1内部表:管理表
hive.metastore.warehouse.dir(例如, /user/hive/warehouse)所定义的目录的子目录下。数据上传到对应目录的文件下。
1.普通创建表
create table if not exists student( id int, name string ) row format delimited fields terminated by 't' stored as textfile location '/user/hive/warehouse/student';
2.从查询中得到表
create table if not exists student2 as select id, name from student;
3.根据已经存在的表结构创建表
create table if not exists student3 like student;
4.查看查询表的类型
desc formatted student2;4.2 外部表
外部表是Hive 并非认为其完全拥有这份数据。删除该表并不会删除掉这份数据,不过描述表的元数据信息会被删除掉。
你创建表的时候,其实,数据已经在HDFS了。,但是不是在你的默认目录,需要在创建表的时候指定。
create external table nx_student() row .... location "/aa/bb/ccc"
目录:
管理表和外部表的使用场景:
网站日志流入hdfs建立外部表进行分析,对数据中间结果存储使用内部表
管理表与外部表的互相转换:
修改内部表 student2 为外部表external=true 是外表。
alter table student2 set tblproperties('EXTERNAL'='TRUE');
修改外部表 student2 为内部表
alter table student2 set tblproperties('EXTERNAL'='FALSE')
4.3 修改表
重命名表
ALTER TABLE table_name RENAME TO new_table_name
更新列
增加/修改/替换列信息
--修改 alter table dept change column deptdesc desc string; --添加列 alter table dept add columns(deptdesc string); alter table dept replace columns(deptno string, dname string, loc string);4.4 删除表
drop table dept;4.5 清空表
truncate table student;4.6分区表
分区表实际上就是对应一个 HDFS 文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive 中的分区就是分目录, WHERe 子句中的表达式选择查询所需要的指定的分区。
数据仓库的默认路径:/user/hive/warehouse/ 库路径:nxde1.db 表路径:nx_student 分区:city=beijing city=shanghai 数据文件:stduent.txt 当前表的数据存储目录的完整路径: /user/hive/warehouse/nxde1.db/nx_student/city=shanghai/stduent.txt create table student_ptn(id int, name string) partitioned by(age int)
要点:分区字段一定不能和表一样,但是在使用的时候,分区字段和表字段不同!以前,数据直接放在表目录中,现在,在表目录中,再创建文件夹,每个文件夹包管了这个表的一部分数据。也就意味着:一张表的数据,可以被分门别类的进行管理。
生产环境中,绝大部分的事实表,都是分区表(大部分的分区字段,也都是 date 类型:按天分区的概率是最大的)
创建分区表语法
create table dept_partition( deptno int, dname string, loc string ) partitioned by (month string) row format delimited fields terminated by 't';
加载数据到分区表中
load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201709');
查询分区表中数据
select * from dept_partition where month='201708'
查询多分区
select * from dept_partition where month='201709' union select * from dept_partition where month='201708' union select * from dept_partition where month='201707';
增加分区
创建单个分区
alter table dept_partition add partition(month='201706') ;
同时创建多个分区
alter table dept_partition add partition(month='201705') partition(month='201704');
删除分区
alter table dept_partition drop partition (month='201704'); alter table dept_partition drop partition (month='201705'), partition (month='201706');
查看分区
show partitions dept_partition;
创建二级分区表
create table dept_partition2( deptno int, dname string, loc string )partitioned by (month string, day string) row format delimited fields terminated by 't';
导入数据到二级分区
load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition2 partition(month='201709', day='13');
把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式
(一)方式一: 上传数据后修复
dfs -mkdir -p /user/hive/warehouse/dept_partition2/month=201709/day=12; dfs -put /opt/module/datas/dept.txt /user/hive/warehouse/dept_partition2/month=201709/day=12;
执行修复命令
msck repair table dept_partition2; --查询 select * from dept_partition2 where month='201709' and day='12'
方式二:上传数据后添加分区
--上传数据到固定的目录下 alter table dept_partition2 add partition(month='201709',day='11'); select * from dept_partition2 where month='201709' and day='11';
方式三:创建文件夹后 load 数据到分区
dfs -mkdir -p /user/hive/warehouse/dept_partition2/month=201709/day=10; load data local inpath '/opt/module/datas/dept.txt' into table dept_partition2 partition(month='201709',day='10'); select * from dept_partition2 where month='201709' and day='10';4.7 分桶表
分区是按照文件夹的形式来组织区分
分桶是按照文件的形式来组织区分(分桶的规则:和默认的mapreduce的HashPartitioner 一模一样!)
create table student_bck(id int, name string, age int) clustered by (name) sorted by (age desc) into 3 buckets; --创建分桶表时,数据通过子查询的方式导入普通的表创建如何插入分桶表 create table stu(id int, name string) row format delimited fields terminated by 't'; load data local inpath '/opt/module/datas/student.txt' into table stu; --设置它的属性才能 set hive.enforce.bucketing=true; //开启分桶功能 set mapreduce.job.reduces=-1;//根据分桶个数来确定 insert into table stu_buck select id, name from stu;
这张表中的数据,按照name字段划分成三个文件来进行管理,每个文件中的数据会按照age降序排序规则就是跟MR中的默认hash散列组件的逻辑一样的。
5.DML 5.1 数据导入规则1.向表中装载数据(Load)
load data [local] inpath '数据的 path' [overwrite] into table student [partition (partcol1=val1,…)];
load data:表示 加载数据
local:表示从本地加载数据到 hive 表; 否则从 HDFS 加载数据到 hive 表
inpath:表示加载数据的路径
overwrite:表示覆盖表中已有数据,否则表示追加
into table:表示加载到哪张表
student:表示具体的表
partition:表示上传到指定分区
创建一张表
create table student(id string, name string) row format delimited fields terminated by 't'; load data local inpath '/opt/module/hive/datas/student.txt' into table default.student;
2.通过查询语句向表中插入数据(Insert)
create table student_par(id int, name string) row format delimited fields terminated by 't'; insert overwrite table student_par select id, name from student where month='201709';
insert into: 以追加数据的方式插入到表或分区, 原有数据不会删除
insert overwrite: 会覆盖表中已存在的数据
3.查询语句中创建表并加载数据(As Select)
create table if not exists studen as select id, name from student;
4.创建表时通过 Location 指定加载数据路径
create external table if not exists student5( id int, name string ) row format delimited fields terminated by 't' location '/student;
5.import数据到指定 Hive 表中
import table student2 from '/user/hive/warehouse/export/student';5.2 数据导出规则
1.将查询的结果导出到本地
insert overwrite local directory '/opt/module/hive/data/export/student' select * from student;
2.将查询的结果格式化导出到本地
insert overwrite local directory '/opt/module/hive/data/export/student1' ROW FORMAT DELIMITED FIELDS TERMINATED BY 't' select * from student
3.将查询的结果导出到 HDFS 上
insert overwrite directory '/user/atguigu/student2' ROW FORMAT DELIMITED FIELDS TERMINATED BY 't' select * from student;
4.Hadoop 命令导出到本地
export table default.student to '/user/hive/warehouse/export/student';
export 和 import 主要用于两个 Hadoop 平台集群之间 Hive 表迁移
5.3 查询SELECt [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERe where_condition] [GROUP BY col_list] [ORDER BY col_list] [CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY col_list] ] [LIMIT number] limit:典型的查询会返回多行数据。 LIMIT 子句用于限制返回的行数。 in 有或的意思5.3.1 别名
select ename AS name, deptno dn from emp;5.3.2 Like 和 RLike
% 代表零个或多个字符(任意个字符)。
_ 代表一个字符。
RLIKE 子句
RLIKE 子句是 Hive 中这个功能的一个扩展,其可以通过 Java 的正则表达式这个更强大
1)查找名字以 A 开头的员工信息 select * from emp where ename LIKE 'A%'; (2)查找名字中第二个字母为 A 的员工信息 select * from emp where ename LIKE '_A%'; (3)查找名字中带有 A 的员工信息 select * from emp where ename RLIKE '[A]';5.3.3 groupby
GROUP BY 语句通常会和聚合函数一起使用,按照一个或者多个列队结果进行分组,然后对每个组执行聚合操作。多列groupby多列,列名之间用逗号隔开。
5.3.4having 与 where 不同点(1) where 后面不能写分组函数, 而 having 后面可以使用分组函数。
(2) having 只用于 group by 分组统计语句。
--求每个部门的平均薪水大于 2000 的部门 select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 20005.3.5 内连接和外连接
内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。
左外连接
左外连接: JOIN 操作符左边表中符合 WHERe 子句的所有记录将会被返回。
右外连接
右外连接: JOIN 操作符右边表中符合 WHERe 子句的所有记录将会被返回。
union去重,unionall 不去重
如果需要去重复,用union
不需要去重复,用union all
如果不存在重复,用union all和union 一样用unionall
SELECt e.ename, d.dname, l.loc_name FROM emp e JOIN dept d ON d.deptno = e.deptno JOIN location l ON d.loc = l.loc;5.3.8hive排序:
Order By: 全局排序, 只有一个 Reducer
1) 使用 ORDER BY 子句排序
ASC(ascend) : 升序(默认)
DESC(descend) : 降序
1.按一列order by列名.
2.多列orderby多列,列名之间用逗号隔开.
select * from student order by age; select * from student sort by age; select * from student distribute by age; select * from student cluster by age;5.3.8.1 全局排序
order by最终使用一个reduceTask来完成排序,如果数据量很大,使用order by来排序是不明智的。
5.3.8.2 sort by 局部排序!假设你使用多个reduceTask来运行的话,那么每个reduceTask输出的结果是有序的。但是所有的结果放在一起是没有顺序的.
我的数据量确实很大(不能使用orderby来进行全局排序),但是需求就是要进行全局排序?思路参考Hbase的设计!(范围分区 + 局部有序)
distribute by 类似partition 进行分区,结合sortby 使用。
先分区然后按照order by
分桶查询, 有条件: 1、必须设置 reduceTask 的个数: set mapreduce.job.reduces=4 2、查询中,必须设置 distribute by 来设置分桶规则:hash散列5.3.8.4 cluster by 分桶排序
如果 sort by 的字段和 distribute by 的字段一样,就可以简写:
cluster by age = distribute by age sort by age;
只有这种情况能简写,除此之外,都不可以。
cluster by 只能升序排序。
`



