内部表,外部表,分区表,分桶表

206 阅读6分钟

表分类

Hive中可以创建的表有好几种类型, 分别是:
内部表:又叫管理表或者托管表
    分区表(分区分桶表)
    分桶表
外部表:又叫非管理表或者非托管表
    分区表(分区分桶表)
    分桶表
    

内部表和外部表区别?
内部表: 未被external关键字修饰的即是内部表, 即普通表。 内部表又称管理表,还可以叫托管表
        删除内部表:直接删除元数据(metadata)和存储数据本身
        可以用as来复制表结构以及其中的数据,可以用truncate清空表数据
        对表有着绝对的控制权
外部表: 被external关键字修饰的即是外部表, 即关联表。 还可以叫非管理表或非托管表
        删除外部表:仅仅是删除元数据(metadata),不会删除存储数据本身
        不可以用as来复制表结构以及其中的数据,不可以用truncate清空表数据
        对表没有绝对控制权
	
查看表格式化信息: desc formatted 表名; 
	-- 内部表类型: MANAGED_TABLE
	-- 外部表类型: EXTERNAL_TABLE

分区表

分区表.jpg

分区表特点/好处:需要产生分区目录, 查询的时候使用分区字段筛选数据,避免全表扫描从而提升查询效率

效率上注意: 如果分区表,在查询数据的时候没有使用分区字段去筛选数据,效率不变

分区字段名注意: 分区字段名不能和原有字段名重复,因为分区字段名要作为字段拼接到表后

分桶表

分桶表.jpg

分桶表特点/好处:需要产生分桶文件, 查询的时候特定操作上提升效率(过滤,join,分组 以及 抽样)

效率上注意: 如果分桶表,在查询数据的时候没有使用分桶字段去筛选数据,效率不变

分桶字段名注意: 分桶字段名必须是原有字段名, 因为分桶需要根据对应字段值取余数把余数相同的数据放到同一个分桶文件中

分桶原理

分桶原理: 
如果是数值类型分桶字段: 直接使用数值对桶数量取模   
如果是字符串类型分桶字段: 底层会使用hash算法计算出一个数字然后再对桶数量取模

Hash: Hash是一种数据加密算法,其原理我们不去详细讨论,我们只需要知道其主要特征:同样的值被Hash加密后的结果是一致的
举例: 字符串“binzi”被Hash后的结果是93742710(仅作为示意),那么无论计算多少次,字符串“binzi”的结果都会是93742710。
计算余数: hash('binzi')%3==0  
注意: 同样的数据得到的结果一致,如’binzi’ hash取模结果是0,无论计算多少次,它的取模结果都是0

分区表和分桶表区别

分区表
	创建表的时候使用关键字: partition by (分区字段名 分区字段类型)
	分区字段名注意事项: 是一个新的字段,需要指定类型,且不能和其他字段重名
	分区表好处: 使用分区字段作为条件的时候,底层直接找到对应的分区目录,能够避免全表扫描,提升查询效率
	分区表最直接的效果: 在hfds表目录下,分成多个分区目录(year=xxxx,month=xx,day=xx)
	不建议直接上传文件在hdfs表根路径下: 分区表直接不能识别对应文件中数据,因为分区表会找分区目录下的数据文件
	使用load方式加载hdfs中文件: 本质是移动文件到对应分区目录下

分桶表
	创建表的时候使用关键字: clustered by (分桶字段名) into 桶数量 buckets
	分桶字段名注意事项: 是指定一个已存在的字段,不需要指定类型
	分桶表好处: 使用分桶字段做抽样等特定操作的时候,也能提升性能效率
	分桶表最直接的效果: 在hdfs表目录或者分区目录下,分成多个分桶文件(000000_0,000001_0,000002_0...)
	不建议直接上传文件在hdfs表根路径下: 分桶表可以识别对应文件中数据,但是并没有分桶效果,也是不建议的
	使用load方式加载hdfs中文件: 本质是复制数据到各个分桶文件中

复杂类型

hvie的SerDe机制

hvie的SerDe机制.jpg

其中ROW FORMAT是语法关键字,DELIMITED和SERDE二选其一。本次我们主要学习DELIMITED关键字相关知识点
如果使用delimited: 表示底层默认使用的Serde类:LazySimpleSerDe类来处理数据。
如果使用serde:表示指定其他的Serde类来处理数据,支持用户自定义SerDe类。

Hive默认的序列化类: LazySimpleSerDe
包含4种子语法,分别用于指定字段之间、集合元素之间、map映射 kv之间、换行的分隔符号。
在建表的时候可以根据数据的类型特点灵活搭配使用。
COLLECTION ITEMS TERMINATED BY '分隔符' : 指定集合类型(array)/结构类型(struct)元素的分隔符
MAP KEYS TERMINATED BY '分隔符' : 表示映射类型(map)键值对之间用的分隔

复杂类型

复杂类型建表格式: 
...
[row format delimited] # hive的serde机制
    [fields terminated by '字段分隔符'] # 自定义字段分隔符固定格式
    [collection ITEMS terminated by '集合分隔符'] # 自定义array同类型集合和struct不同类型集合
    [map KEYS terminated by '键值对分隔符'] # 自定义map映射kv类型
    [lines terminated by '\n'] # # 默认即可
...;

hive复杂类型:   array  struct  map

array类型: 又叫数组类型,存储同类型的单数据的集合
	 建表指定类型:  array<数据类型>
	 取值: 字段名[索引]   注意: 索引从0开始
	 获取长度: size(字段名)
	 判断是否包含某个数据: array_contains(字段名,某数据)

struct类型: 又叫结构类型,可以存储不同类型单数据的集合
	 建表指定类型: struct<子字段名1:数据类型1, 子字段名2:数据类型2 , ...>
	 取值: 字段名.子字段名n
	
map类型: 又叫映射类型,存储键值对数据的映射(根据key找value)
	建表指定类型: map<key类型,value类型>
	取值: 字段名[key]
	获取长度: size(字段名)
	获取所有key: map_keys()
	获取所有value: map_values()