1. 什么是 HIVE
Hive 是建立在Hadoop 上的数据参考基础架构,它提供了一系列的工具,可以来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。
Hive定义了简单的类SQL查询语言,成为QL,它允许SQL的用户查询数据。同时,这个语言也允许熟悉MapReduce开发者的开发自定义的mapper和Reduce来处理内奸的mapper和reduce日无法完成的复杂分析工作。
Hive是sql解析引擎,它将SQL语句转译成MapReduce job然后在Hadoop执行
hive的表其实就是HDFS的文件夹,表里面的数据对应的是文件夹里面的文件,按表名把文件夹分开,如果是分区表,则分区值是子文件夹,可以直接在MapReduce job里使用这些数据
2. Hive的系统架构
- 用户接口主要有三个,包括CLI,JDBC/ODBC,WebUI
CLI: 即shell命令行
JDBC/ODBC 是hive的Java,与使用传统数据库JDBC的方式类似
WebUI 是通过浏览器访问hive
- hive将元数据存储在数据库中(metastore),目前只支持mysql、derby。
hive中的元数据包括表的名字,表的列和分区机器属性,表的属性(是否为外部表等),表的数据所在目录等。
解释器、编译器、优化器完成HQL查询语句从词法分析,语法分析、编译、优化以及查询计划(plan)的生成。生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行
hive的数据存储在HDFS中,大部分的查询由MapReduce完成(包含*的查询,比如select * from table 不会生成MapReduce任务)
Hadoop:利用HDFS进行存储利用MapReduce进行计算
3. 安装hive
- Hive只在一个节点上安装即可
上传tar包
解压
1 | tar -zxvf hive-0.9.0.tar.gz -C /cloud/ |
- 配置mysql metastore
1 | 配置HIVE_HOME环境变量 |
- 配置hive
1 | cp hive-default.xml.template hive-site.xml |
- 安装hive和mysq完成后,将mysql的连接jar包拷贝到$HIVE_HOME/lib目录下
如果出现没有权限的问题,在mysql授权(在安装mysql的机器上执行)
1 | mysql -uroot -p |
遇到的异常详情如下:
1 | Exception in thread "main"java.lang.RuntimeException: java.lang.IllegalArgumentException:java.net.URISyntaxException: Relative path in absolute URI:${system:java.io.tmpdir%7D/$%7Bsystem:user.name%7D |
- 解决方案如下:
1.查看hive-site.xml配置,会看到配置值含有”system:java.io.tmpdir”的配置项
2.新建文件夹/opt/hive-3.1.1/tmp
3.将含有”system:java.io.tmpdir”的配置项的值修改为如上地址
启动hive,成功!
4. metaStore 初始化
1 | ./schematool -initSchema -dbType mysql |
5. msyql对应meta元数据
| TBLS | 对应表 |
|---|---|
| Columns_v2 | 对应列 |
| Sds | 对应目录 |
6. 数据类型
6.1 基本数据类型
| 整数类型 | tinyint、smallint、int、bigint |
|---|---|
| 浮点类型 | float、 double |
| 布尔类型 | boolean |
| 字符串类型 | string |
| 字符串 | varchar 从0.12.0开始支持 |
| 字符 | char 从0.13.0开始支持 |
1 | -- 建表 |
6.2 时间类型
| 数据类型 | 说明 |
|---|---|
| Timestamp | 存储系统时间戳,秒数 从hive0.8.0开始支持 |
| Date | 描述特定日期 yyyy-mm-dd 只包含日期 没有时间 从hive0.12.0开始支持 |
6.3 复杂数据类型
MAP KEYS TERMINATED BY :key value分隔符
FIELDS TERMINATED BY:字段与字段之间的分隔符
COLLECTION ITEMS TERMINATED BY:一个字段各个item的分隔符
| 复杂数据类型 | 说明 |
|---|---|
| Array | 数组类型,由一系列相同的数据类型的元素构成 |
| Map | 集合类型,包含key->value 键值对,可以通过kay来访问元素 |
| Struct | 结构类型,可以包含不同数据类型的元素,这些元素可以通过“点语法”的方式得到所需要的元素 |
| Union | Union类型,可以在同一时间点,保持恰好有一个指定的数据类型。 您可以使用create_union的UDF创建一个实例的类型,从0.7.0开始提供 |
- Array
1 | -- 指定array中元素之间的分隔符 COLLECTION ITEMS TERMINATED BY ',' |
- Map
1 | -- 指定map中元素之间的分隔符,map与key之间为: 元素之间为, |
- Struct
1 | -- 指定struct之间的分隔符:COLLECTION ITEMS TERMINATED BY ':' |
- 嵌套复杂结构类型
1 | -- 创建表 |
7. Hive数据存储
- 基于HDFS
- 没有专门的数据存储格式
- 存储结构主要包括:数据库、文件、表、视图
- 可以直接接在文本文件(.txt文件等)
- 创建表时,指定hive数据的列分隔符与行分隔符
7.1 内部表
- 与数据库中的Table 在概念上是类似的
- 每个table在hive中都有一个相应的目录存储数据
- 所有的table数据(不包括external table)都保存在这个目录中
- 删除表的时候,元数据与数据都会被删除
7.1.1 创建表
- 创建一张内部表(默认创建在user/hive/warehouse文件夹下)
1 |
|
- 创建表到指定路径
1 | -- 默认列的分隔符是制表符 |
- 创建表并指定分隔符
1 | hive> Create table t3(tid int,tname string,age int) row format delimited fields terminated by '\t'; |
- 通过查询结果创建一张新的表
1 | hive> Create table t4 as select * from t3; |
- 通过查询结果创建表
1 | hive> Create table t5 row format delimited fields terminated by '\t' as select * from t3; |
- 创建表指定保存文件类型
1 | hive> Create table t5 row format delimited fields terminated by '\t' as select * from t3 stored as textfile; |
- 创建完整表
1 | create table machine_login_log_bak( |
7.1.2 更新表结构
7.1.2.1 增加列
1 | hive> Alter table t1 add columns (english int); |
7.1.2.2 增加列并增加注释
1 | hive> ALTER TABLE t1 ADD COLUMNS (history INT COMMENT 'a comment'); |
7.1.2.3 更改表名
1 | hive> ALTER TABLE t1 RENAME TO t1_bak; |
7.1.2.4在表的最后增加列
1 | --在表的最后增加一列字段 |
7.1.2.5用新列替换原表中的所有列
REPLACE:则是表示替换表中所有字段。
1 | --替换原表中的所有字段 |
7.1.2.6增加表的元数据信息
1 | 用户可以用这个命令向表中增加metadata |
7.1.2.6 改变表文件格式与组织
1 | -- 这个操作修改了表的物理存储属性 |
7.1.2.7 修改列的名字、类型、位置、注释
1 | hive> ALTER TABLE t1_bak CHANGE COLUMN pen clour int COMMENT 'change comment'; |
7.1.3 删除表
1 | hive> Drop table t1_bak; |
7.1.4 清空表
1 | insert overwrite table t_table1 select * from t_table1 where 1=0; |
7.2 分区表 (Partition )
Partition 对应数据库的partition列的密集索引
在hive中,表的一个partition对应与表下的一个目录,所有的partition的数据都存储在对应的目录中
示例数据
1 iverson M 60 80 96
2 KOBE M 67 80 95
3 T-MAC F 59 67 86
4 DALA M 58 68 95
5 PARK M 75 62 58
6 curry F 58 68 69
7 wade M 85 69 85
8 yaom F 75 85 65
9 bosh F 58 94 26
10 GREEN M 24 98 78
7.2.1 创建分区表
1 |
|
7.2.2 查询数据插入分区表的指定分区
1 | insert into table partition_table partition (gender=’M’) select sid,sname from samp_data where gender=’M’; |
7.2.3 查看分区
1 | show partitions partition_table |
7.2.4 添加分区
1 | -- 添加分区并创建二级分区 |
7.2.5 删除分区
1 | Alter table partition_table drop if exists partition (gender='X',type='text'); |
7.2.6 hive动态分区
7.2.6.1动态分区的几个参数
1 | -- 使用动态分区 |
2.2.6.2动态分区表插入数据
- 分区字段需要在查询的末尾,如果多等分区 分区字段的顺序要跟分区一致
1 | -- 1.创建分区表 |
7.2.6.3 动态生成二级分区向表中插入数据
分区字段需要在查询的末尾,如果多等分区 分区字段的顺序要跟分区一致
1 | Insert into table d_part partition(value,sex)Select name,age as value,sex as sex from t1; |
7.3.外部表(external table)
指向已经存在HDFS中存在的数据,可以创建partition
它和内部表在元数据的组织上是相同的,而实际数据的存在则有较大差异
外部表只有一个过程,加载数据和创建表同时完成,并不会移动数据到仓库目录中,只是与外部数据建立一个链接,当删除外部表时,仅删除该链接
7.3.2 创建外部表
1 | create table external_student (sid int,sname string,age int) row format delimited terminated by ‘,’location ‘/input’; |
7.3.3 内部表转外部表
1 | hive> alter table t1 set TBLPROPERTIES ('EXTERNAL' = 'TRUE'); |
7.3.4 外部表转内部表
1 | hive> alter table t2 set TBLPROPERTIES('EXTERNAL'='FALSE'); |
7.4.桶表(bucket table)
对于每一张表(table)或者分区,hive可以进一步组织成同,也就是说同是更为细粒度的数据范围划分
hive 是针对某一列进行分桶
hive 采用对列值哈西,然后除以同的个数求余的方式决定该条记录存放在哪一个桶中
好处
- 获得更高的查询效率
- 是取样(sampling)更高效
7.4.1 创建桶表
1 | -- 设置开启分桶功能 |
7.5 视图(view)
1.视图是一种虚表,是一个逻辑概念,可以跨越多张表
2.视图建立在已有的表的基础之上,视图依赖以建立的这些表成为基表
3.视图可以简化复杂的查询
使用方法:在mysql控制台里依次执行即可,将生成和oracle里scoot/tigger下完全一样的测试用示例表。方便需要测试数据l的使用mysql的同学
1 | -- 建立视图 |
8. 数据导入导出
8.1 数据导入
- 使用load语句加载数据
1 | Load data [local] inpath 'filepath' [override] |
| 命令 | 含义 |
|---|---|
| Load data | 导入数据 |
| [local] | 导入数据的位置 添加local 说明从linux本地文件导入, 不添加从hdfs中导入 |
| inpath ‘filepath’ | 文件地址 |
| [override] | 是否要覆盖表中原有的数据, 添加override会先删除表中原有的数据,然后添加新的数据 不添加override则在表中新增数据 |
| tablename | 要导入数据的表名 |
| [partition (partcol1 = val1,partcol2 = val2…)] | 将数据导入到哪个分区当中,后面是分区条件 |
1 | -- 在原来的数据基础上新增 |
8.2 导出数据
1 | -- 1. 导出到本地文件系统 |
9. 数据查询
9.1 简单查询
1 | -- 查看表结构 |
9.2 使用distinct去重
1 | Select distinct deptno from dept; |
9.3 Where 查询
1 | -- 查询10号部门的员工 |
9.4 模糊查询
1 | -- 查询名字以S开头的员工 |
9.5 排序
1 | -- 查询员工信息:员工号,姓名,月薪按照月薪排序 |
9.6 Hive 的表连接
- 等值连接
1 | --查询 员工号,姓名,月薪,部门名称 |
- 不等值连接
1 | -- 查询员工号,姓名,月薪,工资级别 between and 包含两个值,小值在前 大值在后 |
- 外连接
1 | -- 按部门统计员工人数: 部门号,部门名称,人数 |
- 右外连接
通过外连接可以将对于连接条件不成立的记录仍然包含在最后的结果中
1 | -- 列出所有部门与员工数 |
- 自连接
自连接的核心是通过表的别名将同一张表视为多张表
1 | -- 查询员工的姓名和员工老板的姓名 |
9.7 hive子查询
hive只支持 from 和 where子句中的子查询
1 | select |
- 子查询注意问题
语法中的括号
书写风格
hive中只支持where和from子句中的子查询
主查询和子查询可以不是同一张表
如果子查询返回的结果集有空值的话不可以使用not in 但是可以使用in
10. 使用 Java 操作 HIVE
- 启动hive远程服务 后台运行
1 | hive --service hiveserver & |
10.1 使用 JDBC 方式连接 hive
打开ide 新建Java项目 导入hive驱动(从hive lib目录下可以找到(hive-jdbc.jar))
1 | package hvie; |
1 | package hvie; |
10.2 使用 Thrift client 方式连接 hive
1 | package hvie; |
11. 自定义 UDF
hive自定义函数(UDF User Defined Function) : 可以直接处理应用与select语句,对于查询结果做格式化处理后,再输出内容
自定义UDF需要继承 org.apache.hadoop.hive.ql.UDF,需要实现evaluate函数,evaluate函数支持重载
把程序打包放到目标机器上去,进入hive客户端,添加jar包,Hive -add jar /root/udf-test.jar
创建临时函数
Hive> create temporary function <函数名> as ‘Java类名’;
自定义函数的使用
Select <函数名> from table;
销毁自定义函数
Hive> drop temporary function <函数名>
Hvie 自定义函数案例(拼接两个字符串)
1 | package hvie; |
导出jar文件,并上传到服务器,
创建临时函数
1 | create temporary function intersection as 'hvie.ListIntersectionUDF'; |