定义
hive是一个构建在hadoop上的数据仓库框架。可以将结构化的数据文件映射为一张数据库表,并提供完整的sql查询功能,可以将sql语句转换为mapreduce任务进行运行。 其优点是学习成本低,可以通过类sql语句快速实现简单的mapreduce统计,不必开发专门的mapreduce应用,十分适合数据仓库的统计分析。(来自百度百科~~)
metastore
metastore是hive元数据的集中存放地,metastore包括两部分:服务和后台数据的存储。默认情况下,元数据存储在derby数据库实例中。由于是本地数据库且不支持并发访问,故多作为练手使用。还一种使用其他数据库的方式称为“local metastore”,支持并发访问,但metestore服务仍然和hive服务运行在同一个进程中,故称之为本地metastore。还有第三种方式:“remote metastore”,metastore无武器和hive服务运行在不同的进程内,可以提供更好的可管理性和安全性。(怎么配local metastore和remte metastore先不搞了,先拿默认方式练手为主~)
和传统数据库的比较
最本质的一点,hive依赖于hdfs和mapreduce!
在传统数据库里,表的模式是在数据加载时强制确定的(写时模式,schema on write),而hive对数据的验证却在查询时进行(读时模式,schema on read);读时模式有利于数据加载,基本上就是纯粹的复制粘贴,且更加灵活,可以以各种不同模式来分析数据。写时模式有利于提升查询性能,因为可以建索引,压缩数据等。
hive不支持更新,事务和索引。(暂时不支持吧,将来谁也说不准~)hive是用来以mr的方式操作hdfs数据的,在这种环境下,全表扫描(full-table scan)是常态操作,而表更新则是通过吧数据变换后放入新表实现。事务方面hive并没有对表的并发访问做什么处理,需要应用程序端自己在应用层实现。(比如类似spring事务)
hiveql
不完全支持sql-92标准,支持数值型,布尔型,字符串类型等原子类型;数组,映射,结构等复杂类型。
tinyint,smallint,int,bugint分别对应于java中的byte,short,int,long。
float,double直接对应float,double(废话~)
string对应于string,而没有其他数据库中的 varchar,varchar2,char等类型。hive的string类似于其他数据库中的varchar,但是不能声明最长字符数,理论上string最长为2g。
数据类型转换:
任何类型都可以隐式转换为一个范围更广的类型,所有整数类型,float,string(这个有点奇怪)都可以隐式转换为double,tinyint,smallint,int都可以隐式转换为float,double最大,不能隐式转换为任何类型。
可以使用cast执行显式转换,如果转换失败则返回空值null。
复杂类型:
hive有3中复杂类型:array,map和struct;array,map和java中的类似;struct是一种记录类型,封装了一个命名的字段集合。复杂数据类型允许任意层次的嵌套。
操作:
“||” 不是字符串连接操作符,而是 “或”操作符,concat函数用来作为连接操作
表:
hive表格逻辑上由存储的数据和描述表格中数据形式的相关元数据组成。数据存放在hdfs中,元数据(metastore)存放在关系数据库中。
hive中的表分为托管表(managed table)和外部表(external table)两种。托管表是默认情况,托管表会将数据移入hive的仓库目录(warehouse directory);外部表则直接到外部目录访问数据。
相应的,如果是托管表,load操作将会复制数据到仓库目录,drop操作将会删除表数据和表的元数据,而外部表则需要在create操作时指定外部数据路径,在drop操作时,只删除元数据而不碰外部数据。外部表使用external关键字创建。
普遍的用法是把存放在hdfs中的初始数据集用作外部表使,用hive转换后的数据存入托管表;反过来——外部表可以用作将托管表中的数据导出到hdfs以供其他应用程序使用。
分区和桶
分区的好处是对于同一分区内的数据进行查询的时候将会非常高效,比如按年份分区,查某一年的数据只需要到这个分区中检索就行了。分区是在创建表的时候用 partitioned by 子句定义的。
在load数据的时候则需要指定分区值:
在文件系统中,分区只是表目录下嵌套的子目录。如按分区检索数据其实就是按文件系统目录检索数据了。
show partitions logs; 命令会返回当前表中所有分区信息。partitioned by 子句中的列是表中正式的列,称为分区列。但是数据文件并不包含这些列,因为在目录中包含了。可以像普通列一样使用分区列(partition column)。
桶可以获得更高的查询处理效率;桶可以使取样操作更高效。使用clustered by 子句来制定划分桶所用的列和要划分的桶的个数。
桶对应于mr的输出文件分区:一个作业产生的桶(输出文件)和reduce任务个数相同。由于我本地只有一个伪分布环境,只能一个reduce,所以只得到一个桶,一个桶~

桶文件中包含在这个桶中的记录信息,划分桶的规则是:hive对值进行哈希并将结果除以桶的个数取余数,这样任何一个桶里都会有一个随机的用户集合。
tablesample 子句对表进行取样,这个子句会将查询限定在表的一部分桶内,而不是使用整个表:
存储格式
hive从两个维度对表的存储进行管理:“行格式”(row format)和“文件格式”(file format)。行格式指行和一行中的字段如何存储,行格式由serde定义(serializer-deserializer)
默认格式为分割的文本,每行存储一个数据行。
二进制存储格式:顺序文件和rcfile
hadoop的顺序文件格式是一种针对顺序和记录的通用二进制格式。在hive中,可以在create table 中通过声明stored as sequencefile来使用顺序文件。使用顺序文件一个主要的优点是支持可分割的压缩(splittable)。顺序文件时面相行的,这意味着同一行中的字段作为一个顺序文件记录存储在一起。
rcfile按列记录文件,rcfile把表分成行分片(row split),在每一个分片中先存所有行的第一列,再存第二列,以此类推。通过声明stred as rcfile来使用rcfile存储格式。
面向行的存储格式对于那些只访问表中一小部分行的查询比较有效;面相列的存储格式适合同事处理一列中很多列的情况。
导入数据
create table ... as select
insert overwrite table
load data
三种格式,load data 和 insert overwrite table 上面都有示例了,ctas练手一个吧,还有插入partition的示例,多表插入
ctas操作是原子的,如果select查询由于某种原因失败,是不会创建新表的。
表的操作
drop表就跟其他sql一致了, 如果是外部表,则只删除元数据,外部数据不会受到影响。
查询数据
排序和聚集:
hive的order by子句对数据进行排序,但是order by是通过只用一个reducer来做到这一点的。对于大规模的数据集,效率非常低下。
在很多情况下,并不需要结果是全局排序。此时,可以使用hive的非标准的扩展sort by。
sort by:为每个reducer产生一个排序文件;
distribute by x:确保x列相同的数据在同一个reduce分区中;
内连接:
hive 不支持 where sales.id=things.id 这样的连接操作!
三种外连接:(左外,右外,全外)
半连接:
hive不支持in操作,但是可以使用left semi join 达到相同的效果:(sales表不能再select 后面出现,感觉类似exist了)
指定map连接:
如果有一个连接表小到足以放入内存,hive就可以把较小的表放入每个mapper的内存来执行连接操作。在hive中需要使用注释来指定map连接:
子查询:
hive只支持子查询出现在from子句中
视图:貌似和其他数据库中视图没啥区别,只是保存元数据,而不执行查询,不物化数据。
使用外部脚本:
使用hadoop streaming,transform,map,reduce子句可以在hive中调用外部脚本
用户自定义函数 (user-defined function,udf)
hive有三种udf:普通udf,用户定义聚集函数udaf,用户定义表生成函数udtf。
udf用户操作单个数据行,产生一个数据行作为输出,就像普通函数返回一个返回值;
udaf接受多个输入数据行,产生一个输出数据行,聚集函数好像都如此;
udtf作用于单个数据行,产生多个数据行(一个表)作为输出。
(不想写了~ 这几个鸟函数决定使用到了再来研究了!!!)over