您现在的位置是:首页 > 文章详情

Hadoop学习笔记(三):Hive简介

日期:2015-05-06点击:475

定义

      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 子句定义的。

CREATE TABLE LOGS(ts BEGINT,line STRING) PARTITIONED BY (dt STRING,country STRING);

       在LOAD数据的时候则需要指定分区值:

 LOAD DATA LOCAL INPUT 'input/hive/partitions/file1' INTO TABLE logs PARTITION (dt='2001-1-1',country='GB');

 

       在文件系统中,分区只是表目录下嵌套的子目录。如按分区检索数据其实就是按文件系统目录检索数据了。

       SHOW PARTITIONS logs; 命令会返回当前表中所有分区信息。PARTITIONED BY 子句中的列是表中正式的列,称为分区列。但是数据文件并不包含这些列,因为在目录中包含了。可以像普通列一样使用分区列(partition column)。

select ts,dt,line from logs  where country='GB'

 

       桶可以获得更高的查询处理效率;桶可以使取样操作更高效。使用CLUSTERED BY 子句来制定划分桶所用的列和要划分的桶的个数。

create table bucketed_records(year int,temperature STRING,quality STRING,station STRING) clustered by (year) sorted by (year ASC) into 4 buckets;

 

 insert overwrite table bucketed_records select * from records;

        桶对应于MR的输出文件分区:一个作业产生的桶(输出文件)和reduce任务个数相同。由于我本地只有一个伪分布环境,只能一个reduce,所以只得到一个桶,一个桶~

        桶文件中包含在这个桶中的记录信息,划分桶的规则是:Hive对值进行哈希并将结果除以桶的个数取余数,这样任何一个桶里都会有一个随机的用户集合。

        TABLESAMPLE 子句对表进行取样,这个子句会将查询限定在表的一部分桶内,而不是使用整个表:

 select * from bucketed_records tablesample(bucket 1 out of 4 on year);

 

存储格式

       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的示例,多表插入

create table test_records(year int,temperature STRING,quality STRING,station STRING) as select * from records;
insert overwrite table target partition (dt='xxx') select col1,col2 from source;
insert overwrite table target partition (dt) select col1,col2,dt from source;
from souce insert overwrite table table1 select col1,col2 insert voerwrite table tablw2 select col3,col4 ...;

CTAS操作是原子的,如果SELECT查询由于某种原因失败,是不会创建新表的。

表的操作

 该语句可以将更新元数据并且将表目录移动到新名称所对应的目录下:
alter table source rename to target;
 添加一个新列:
alter table target add columns (col3 string);

      drop表就跟其他sql一致了, 如果是外部表,则只删除元数据,外部数据不会受到影响。


查询数据

   排序和聚集:

      Hive的Order By子句对数据进行排序,但是Order By是通过只用一个Reducer来做到这一点的。对于大规模的数据集,效率非常低下。

      在很多情况下,并不需要结果是全局排序。此时,可以使用Hive的非标准的扩展SORT BY。

        SORT BY:为每个reducer产生一个排序文件;

        DISTRIBUTE BY X:确保X列相同的数据在同一个reduce分区中;

select year,temperature from records distribute by year sort by temperature desc;

   内连接:

      Hive 不支持 where sales.id=things.id  这样的连接操作!

select * from sales.*,things.* from sales join things on (sales.id = things.id);

   

   三种外连接:(左外,右外,全外)

select * from sales.*.things.* from sales left outer jion things on (sales.id=things.id); select * from sales.*.things.* from sales right outer jion things on (sales.id=things.id); select * from sales.*.things.* from sales full outer jion things on (sales.id=things.id);

    半连接:

        Hive不支持IN操作,但是可以使用left semi join 达到相同的效果:(sales表不能再select 后面出现,感觉类似exist了)

select * from things left semi join sales on (sales.id=things.id);

    指定map连接:

       如果有一个连接表小到足以放入内存,Hive就可以把较小的表放入每个mapper的内存来执行连接操作。在Hive中需要使用注释来指定map连接:

select /*+ MAPJOIN(things) */ sales.*,things.* from sales join things on (sales.id=things.id);

 

    子查询:

        Hive只支持子查询出现在From子句中

select col1,col2 from (select * from records where ... ) a

 

    视图:貌似和其他数据库中视图没啥区别,只是保存元数据,而不执行查询,不物化数据。

    使用外部脚本:

        使用Hadoop Streaming,TRANSFORM,MAP,REDUCE子句可以在Hive中调用外部脚本

ADD FILE /test.py; SELECT TRANSFORM(COL1,COL2,COL3) FROM TABLE USING 'test.py' AS COL1,COL2; --TRANSFORM(COL1,COL2,COL3) 表示查询本身将把col1,col2,col3作为以制表符分割的行的形式流式传递给脚本test.py

 

 FROM ( FROM table MAP col1,col2,col3 USING 'testmap.py' AS col1,col2) map_output REDUCE col1,col2 USING 'testreduce.py' AS col1,col2;

 

用户自定义函数 (user-defined function,UDF)

      Hive有三种UDF:普通UDF,用户定义聚集函数UDAF,用户定义表生成函数UDTF。

            UDF用户操作单个数据行,产生一个数据行作为输出,就像普通函数返回一个返回值;

            UDAF接受多个输入数据行,产生一个输出数据行,聚集函数好像都如此;

            UDTF作用于单个数据行,产生多个数据行(一个表)作为输出。

     (不想写了~ 这几个鸟函数决定使用到了再来研究了!!!)OVER

 

原文链接:https://yq.aliyun.com/articles/62741
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章