内部表与外部表
-
概念:
- 内部表:也叫管理表,数据文件处于表目录下
- 外部表:数据文件可以不处于表目录下,通过location指定
-
区别:
- 内部表数据文件处于表目录下,删除是将数据文件也删除了
- 外部表不处于目录下,也不会删除数据文件,只会删除元数据
分区表与分桶表
概括: 分区表与分桶表都是优化表
-
区别:
- 分区表可以在表目录下建一个分区,分区字段是逻辑字段,实际不存在,查询时最后显示,分区表是目录级别
- 分桶表是将数据文件经过hash散列之后拆分成几个散列二进制文件,无法直接查看,hive自解析,分桶字段是物理字段,实际存在,分桶表是文件级别
-
意义:
- 分区表 意义在于避免全表扫描,通过sql指定分区字段,指定查询某个分区数据;
- 分桶表 意义在于进行关联查询时,避免笛卡尔积的产生,得到更高的处理效率,即mr中的分区效果
静态分区和动态分区
- 静态分区: 通过partition字段来指定数据到哪个分区
- 动态分区:
hive中支持可以通过正则加载数据,通过正则表达式来匹配每个字段,使用字段分隔符中的属性分隔符指定
("input.regex"="")
此种方法也适用于加载数据时列的分隔符不固定或者列中包含了分隔符的场景
底层是用正则自定义mapreduce的input阶段和map阶段的处理
数据存储格式
语法: stored as textfile | rcfile | sequencefile | parquet | orc | avro | jsonfile
背景知识: 数据存储文件的存储形式一般分为 行式存储 和 列式存储
-
行式存储: 面向对象思维,将一行的数据放在一起,一行数据即是一条记录
- 优点:
- 一行数据即是一条记录,所以便于 insert/update 操作
- 缺点:
- 每次查询某个字段,会将整行数据都读取出来,导致查询效率较低
- 同一条记录,每个字段类型不一致,导致不容易获得一个高压缩比,即空间利用率低
- 不是每个列都适合做索引,一列是同一个字段数据,不一定唯一
- 优点:
-
列式存储: 将一列的数据存在一起
- 优点:
- 同一列的数据聚集在一行内,所以便于 分析 和 聚合 操作
- 一行内的数据的类型都是一样的,适合压缩算法,可获得高压缩率,减少存储空间和cpu负载
- 任何列都适合做索引,一列即是一条数据,唯一
- 缺点:
- 不便于 insert /update 操作
- 不适合扫描小量的数据
- 优点:
-
实例:
- textfile :行式存储,默认存储格式,默认不做压缩,hive不会对数据进行切分,无法达到并行操作
- sequencefile:行式存储,kv数据,k为文件名, v为文件数据
- orc:列式存储,先根据行组分隔整个表,再在每一个行组内进行按列存储;
- 优点:
1. 具有列式存储的优点
2. 文件可切分,即可以并行计算,节省hdfs存储资源,减少maptask个数
3.支持复杂数据结构 (map等)
4.二进制存储方式,不可以直接读取,自解析 - 特点: 一个orc文件可以分成若干个stripe,一个stripe包含 indexdata,rowdata,stripefooter
- 优点:
- parquet:列式存储,
- 优点:
1. 具有列式存储的优点
2. 二进制方式存储,不可以直接读取,自解析,文件包括元数据和文件数据
- 优点:
总结: 压缩比 orc > parquet > textfile
实际开发中,存储格式一般选择orc或parquet,压缩算法一般选择snappy,因为在压缩比和解压速度都不是极端,而是居中。
DDL
-创建表
create [external] table [if not exists] table_name
[(col_name data_type [comment col_comment],...)] --**字段及字段备注
[comment tab_comment] --**表备注
[partition by (col_name data_type [comment col_comment],...)] --** 分区字段设置
[cluster by (col_name,col_name,..)
[sort by (col_name [ASC|DESC],...)] into num_buckets buckets] --** 分桶字段设置
[row format row_format] --**分隔符设置
[stored as file_format] --**存储格式设置
[location hdfs_path] --**数据文件位置指定
-复制表结构
create [external] table [if not exists] [db_name.]table_name
like existing_table;
-分隔符指定
row format delimited
[fileds terminated by s_char] --** 指定字段分隔符
[collection items terminated by s_char] --** 字段内容分隔符,分隔后组成数组
[map keys terminated by s_char] --**字段内容分隔符,分隔后组成map集合
[lines terminated by s_char] | serde serde_name --**行分隔符
[with sepdeproperties (property_name=property_value,property_name=property_value,...)]
--** 属性分隔符
- 补充:
- 默认分隔符是不可见分隔符'\001',若分隔符不对,程序不会报错,但是查询结果都是null,
- serde是serialize/deserialize的简称,目前用于序列化和反序列化,读取时用serde的deserializer方法,写入时用serde的serializer的方法
- 默认lazysimpleserde的deserialize,
DML
加载数据
加载数据
1.load
load data [local] inpath 'filepath' [overwrite] into table table_name
[partition(partcol1=val1,partcol2=val2,...)]
复制: local inpath 'filepath' 是将本地文件上传到hdfs,若filepath中文件名已存在,则覆盖
移动: inpath 'filepath' 是将hdfs文件移动到指定位置,若filepath中文件名已存在,则覆盖
overwrite:先删后加
2.insert
insert overwrite table table_name select * from table2_name cluster by(col)
若table_name表中结构与table2_name表结构不一致,hive将会尝试进行转换,不一定成功,若失败,则会将失败数据转换为null
3.put
直接使用put命令进行上传
4.修改表结构导入分区数据,参见 ------
多重插入:
from source_table
insert overwrite table table1_name [partition (partcol1=val1,partcol2=val2,...)]
select_statement1
insert overwrite table table2_name [partition (partcol1=val1,partcol2=val2,...)]
select_statement2
动态分区插入:
insert overwrite table table_name partition [parcol1=[val1],parcol2=[val2]...]
select_statement from from_statement
动态分区是通过位置来对应分区值的,不是通过字段名字,即select_statement查询结果字段要和partition 字段一一对应
<补充>:
1.load和insert的区别: load命令是通过修改hdfs从存储目录方式加载数据,而insert底层是通过mr程序加载数据
导出数据
导出表数据:
1.insert overwrite [local] directory 'direcotory' select ....from ....;
2.create table tb_name as select ....;
多重导出:
from source_table
insert overwrite [local] directory 'direcotory1'
select_statement1
insert overwrite [local] directory 'direcotory2'
select_statement2
查询数据
查询数据
select [all | distinct] select_expr,select_expr,...
from table_reference
join table_other on expr
[where where_condition]
[group by col_list [having condition]]
[cluster by col_list | [distribute by col_list] [sort by | order by col_list]]
[limit number]
1.order by 是做全局排序,即底层只会有一个reducetask任务执行
2.sort by 是做局部有序,可以有多个reducetask,在数据进入reducetask之前完成,即保证每个reducer输出内部有序
3.distribute by 根据指定字段将数据分到不同的redcuer执行,分发算法是hash散列。即mr中的分区效果
4.cluster by 除了具有distribute by 功能外,还会对该字段进行升序排列,
即若distribute和sort是同一个字段时 distribute by + sort by = cluster by
关联数据
关联数据
map join: 小表join大表 小表会在分布式缓存中
reduce join: 普通的join 实现方式
smb join: 分桶join,大表join 大表的优化方案,两张表都必须为桶表
注意:
1.hive 在做join时,会缓存join序列中除了最后一个表的所有表记录,
再通过最后一个表将结果序列化到文件系统中,所以在实践中join时,要把最大的那个表写在最后,
2.hive支持等值(=)的join,不支持非等值的join
3.join 发生在where 字句之前
4.join 是不能调换位置的