Hive-数据模型
01 hive数据模型
hive
数据模型关系图如下:
上图,可以看到 hive
主要有几种数据模型,分别是:
DataBase:数据库
Table:表
Partition:分区
Bucket:桶
1.1 DataBase数据库
DataBase
数据库:相当于关系型数据库中的命名空间,作用是将数据库应用隔离到不同的数据库模式中 。
相关的命令:
create database
数据库名;use
数据库名;以及
drop database
数据库名等语句;
1.2 Table表
Table
表:表是由存储的数据以及描述表的一些元数据组成。数据存储再分布式文件系统中,元数据存储在关系型数据库中;
hive
表分四种:
MANGED_TABLE :内部表
EXTERNAL_TABLE:外部表
INDEX_TABLE:索引表
VIRTUAL_VIEW :视图表
相关的命令(查看表的具体信息使用):
desc tablename
desc formatted tablename
1.2.1 内部表
hive
会默认把数据存储到 /user/hive/warehouse
目录里面:
CREATE TABLE managed_table (dummy STRING);
LOAD DATA INPATH '/user/tom/data.txt' INTO table managed_table;
描述: 根据上面的代码,
hive
会把文件data.txt
文件存储在managed_table
表的warehouse
目录下,即hdfs://user/hive/warehouse/managed_table
目录。
1.2.2 外部表
外部表与内部表的行为上有些差别。我们能够控制数据的创建和删除。删除外部表的时候,hive只会删除表的元数据,不会删除表数据(数据路径是在创建表的时候指定的):
CREATE EXTERNAL TABLE external_table (dummy STRING)
LOCATION '/user/tom/external_table';
LOAD DATA INPATH '/user/tom/data.txt' INTO TABLE external_table;
描述:利用EXTERNAL关键字创建外部表,Hive不会去管理表数据,所以它不会把数据移到/user/hive/warehouse目录下
1.3 Partition分区
1.3.1.1 静态分区
把输入数据文件单独插入分区表的叫静态分区;
通常在加载文件(大文件)到 Hive 表的时候,首先选择静态分区;
在加载数据时,静态分区比动态分区更节省时间;
你可以通过
alter table add partition
语句在表中添加一个分区,并将文件移动到表的分区中;我们可以修改静态分区中的分区;
您可以从文件名、日期等获取分区列值,而无需读取整个大文件;
如果要在 Hive 使用静态分区,需要把
hive.mapred.mode
设置为strict
,set hive.mapred.mode=strict
;静态分区是在严格模式进行下;
你可以在 Hive的内部表和外部表使用静态分区。
1.3.1.2 动态分区
对分区表的一次性插入称为动态分区。
通常动态分区表从非分区表加载数据。
在加载数据的时候,动态分区比静态分区会消耗更多时间。
如果需要存储到表的数据量比较大,那么适合用动态分区。
假如你要对多个列做分区,但又不知道有多少个列,那么适合使用动态分区。
动态分区不需要
where
子句使用limit。不能对动态分区执行修改。
可以对内部表和外部表使用动态分区。
使用动态分区之前,需要把模式修改为非严格模式。
set hive.mapred.mode=nostrict
。
1.3.2 Partition分区例子
如上图所示,假如你有一个存储学生信息的表,表名为 student_details
,列分别是 student_id
,name
,department
,year
等。现在,如果你想基于 department
列对数据进行分区。那么属于同一个 department
的学生将会被分在同一个分区里面(在物理上,一个分区其实就是表目录下的一个子目录)。
假如所有 department = EEE
的学生数据被存储在 /user/hive/warehouse/student_details/department=EEE
目录下。那么查询 department
为 EEE
的学生信息,只需要查询 EEE 目录下的数据即可,不需要全表扫描,这样查询的效率就比较高。
而在真实生产环境中,你需要处理的数据可能会有几百
TB
,如果不分区,在你只需要表的其中一小部分数据的时候,你不得不走全表扫描,这样的查询将会非常慢而且浪费资源,可能95%
的数据跟你的查询语句并没有关系。
1.4 Bucket分桶
Bucket通描述:
hive
可以对每一个表或者是分区,进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。hive
是针对表的某一列进行分桶。hive
采用对表的列值进行哈希计算,然后除以桶的个数求余的方式决定该条记录存放在哪个桶中(分桶的好处是可以获得更高的查询处理效率,使取样更高效)。
要使用hive
的分桶功能,首先需要打开hive
对桶的控制:
set hive.enforce.bucketing=true;
分桶表创建命令:
CREATE TABLE table_name
PARTITIONED BY (partition1 data_type, partition2 data_type,….)
CLUSTERED BY (column_name1, column_name2, …)
SORTED BY (column_name [ASC|DESC], …)]
INTO num_buckets BUCKETS;
每个桶只是表目录或者分区目录下的一个文件,如果表不是分区表,那么桶文件会存储在表目录下,如果表是分区表,那么桶文件会存储在分区目录下。所以你可以选择把分区分成 n 个桶,那么每个分区目录下就会有 n 个文件。
1.4.1 分桶特性
数据分桶原理是基于对分桶列做哈希计算,然后对哈希的结果和分桶数取模。分桶特性如下:
哈希函数取决于分桶列的类型。
具有相同分桶列的记录将始终存储在同一个桶中。
使用
clustered by
将表分成桶。通常,在表目录中,每个桶只是一个文件,并且桶的编号是从 1 开始的。
可以先分区再分桶,也可以直接分桶。
此外,分桶表创建的数据文件大小几乎是一样的。
1.4.2 分桶好处
与非分桶表相比,分桶表提供了高效采样。通过采样,我们可以尝试对一小部分数据进行查询,以便在原始数据集非常庞大时进行测试和调试;
由于数据文件的大小是几乎一样的,map 端的 join在分桶表上执行的速度会比分区表快很多。在做map端 join 时,处理左侧表的 map知道要匹配的右表的行在相关的桶中,因此只需要检索该桶即可;
分桶表查询速度快于非分桶表;
分桶的还提供了灵活性,可以使每个桶中的记录按一列或多列进行排序。 这使得 map 端 join 更加高效,因为每个桶之间的 join变为更加高效的合并排序(merge-sort);
1.5 分区与分桶的区别
分区与分桶的区别:
分区和分桶最大的区别就是分桶随机分割数据库,分区是非随机分割数据库;
分区是水平划分,表的部分列的集合,可以为频繁使用的数据建立分区,这样查找分区中的数据时就不需要扫描全表,这对于提高查找效率很有帮助;
分桶是垂直划分,桶是通过对指定列进行哈希计算来实现的,通过哈希值将一个列名下的数据切分为一组桶,并使每个桶对应于该列名下的一个存储文件;
(hive使用对分桶所用的值进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等);
分桶是存储在文件中,分区是存放在文件夹中,分桶要比分区查询效率高。