Hive SQL关键概念
Hive SQL 是Hive 用户使用Hive 的主要工具。Hive SQL 是类似于ANSI SQL 标准的SQL 语言,但两者又不完全相同。Hive SQL 和MySQL 的SQL 方言最为接近,但两者之间也存在显著差异,比如Hive 不支持行级数据插人、更新和删除,也不支持事务等。
(1)数据库
Hive 中的数据库从本质上来说仅仅是一个目录或者命名空间,但是对于具有很多用户和组的集群来说,这个概念非常有用。首先,这样可以避免表命名冲突;其次,它等同于关系型数据库中的数据库概念,是一组表或者表的逻辑组
(2)表
Hive 中的表( Table )和关系数据库中的table 在概念上是类似的,每个table 在Hive中都有一个相应的目录存储数据,如果没有指定表的数据库,那么Hive 会通过{HIVE_HOME} /conf/hive-site且nl 配置文件中的hive.metastore .warehouse. dir 属性来使用默认值(一般是/user/hive/warehouse ,也可以根据实际的情况来修改这个配置),所有的table 数据(不包括外部表) 都保存在这个目录中。
Hive 表分为两类,即内部表和外部表。
a.内部表:
所谓内部表(managed table) Hive 管理的表,Hive 内部表的管理既包含逻辑以及语法上的,也包含实际物理意义上的,即创建Hive 内部表时,数据将真实存在于表所在的目录内,删除内部表时,物理数据和文件也一并删除。
b.外部表:
外部表( external table )其管理仅仅是在逻辑和语法意义上的,即新建表仅仅是 指向一个外部目录而已。同样,删除时也并不物理删除外部目录,而仅仅是将引用和定义 删除。
【案例】
考虑下面的语句:
CREATE TABLE my .... managed_table(coll STRING);
LOAD DATA INPATH ’/user/root/test_data.txt' INTO table my managed table
上述语句会将hdfs://user/root/data且t 移动到Hive 的对应目录hdfs://user/hive/warehouse/managed_ table 。但是载入数据的速度非常快,因为Hive 只是把数据移动到对应的目录,不会对数据是否符合定义的Schema 做校验,这个工作通常在读取的时候进行(即为SchemaOn Read ) 。同时, my_rnanaged_table 使用DROP 语句删除后,其数据和表的元数据都被删除,不再存在, 这就是Hive Managed 的意思:DROP TABLE my_managed_table;
外部表则不一样,数据的创建和删除完全由自己控制, Hive 不管理这些数据。数据的位置在创建时指定:
CREATE EXTERNAL TABLE external_table (dummy STRING)
LOCATION '/user/root/external table';
LOAD DATA INPATH '/user/root/data.txt ’工NTO TABLE external table;
指定EXTERNAL 关键字后,因而不会把数据移动到warehouse 目录中。事实上, Hive甚至不会校验外部表的目录是否存在。这使得我们可以在创建表之后再创建数据。当删除外部表时, Hive 只删除元数据,而不会删除外部实际物理文件。
如果数据的所有处理都在Hive 中进行,那么更倾向于选择内部表。但是如果Hive 和其他工具针对相同的数据集做处理,那么外部表更合适。一种常见的模式是使用外部表访问存储的HDFS (通常由其他工具创建)中的初始数据,然后使用Hive 转换数据并将其结果放在内部表中。相反,外部表也可以用于将Hive 的处理结果导出供其他应用使用。
(3)分区
Hive 将表划分为分区( partition), partition 根据分区字段进行。分区可以让数据的部分查询变得更快。表或者分区可以进一步被划分为桶( bucket ) 。桶通常在原始数据中加人一些额外的结构,这些结构可以用于高效查询。例如,基于用户ID 的分桶可以使基于用户的查询非常快。
假设日志数据中,每条记录都带有时间戳。如果根据时间来分区,那么同一天的数据将被划分到同一个分区中。针对每一天或者某几天数据的查询将会变得很高效,因为只需要扫描对应分区的文件。分区并不会导致跨度大的查询变得低效。分区可以通过多个维度来进行。例如,通过日期划分之后,还可以根据国家进一步划分。
分区在创建表的时候使用PARTITIONED BY 从句定义,该从句接收一个字段列表:
CREATE TABLE logs (ts BIG INT , line STRING)
PARTITIONED BY (dt STRING,country STRING);
当导人数据到分区表时,分区的值被显式指定:
LOAD DATA INPATH ’/user/root/path ’
INTO TABLE logs
PARTITION(dt='2001-01-01',country='GB ’);
(4)分桶
在表或者分区中使用桶通常有两个原因:
一是为了高效查询。桶在表中加入了特殊的结果, Hive 在查询的时候可以利用这些结构提高效率。例如,如果两个表根据相同的字段进行分桶,则在对这两个表进行关联的时候,可以使用map-side 关联高效实现,前提是关联的字段在分桶字段中出现。
二是可以高效地进行抽样。在升析大数据集时,经常需要对部分抽样数据进行观察和分析,分桶有利于高效实现抽样。
为了让Hive 对表进行分桶,通过CLUSTERED BY 从句在创建表的时候指定:
CREATE TABLE bucketed users(id INT, name STRING)
CLUSTERED BY (id) INTO 4 BUCKETS;
指定表根据id 字段进行分桶,并且分为4 个桶。分桶时, Hive 根据字段哈希后取余数来决定数据应该放在哪个桶,因此每个桶都是整体数据的随机抽样。在map-side 的关联中,两个表根据相同的宇段进行分桶,因此处理左边表的bucket时,可以直接从外表对应的bucket 中提取数据进行关联操作。map-side 关联的两个表不一
定需要完全相同bucket 数量,只要成倍数即可。