Hadoop权威指南--Hive笔记

关于Hive
Hive是一个构建在Hadoop上的 数据仓库 框架
SQL语句不适合开发复杂的机器学习算法
Hive把SQL查询转换为一系列在Hadoop集群上运行的MapReduce作业
Hive把数据组织为表,通过这种方式为存储在hdfs的数据赋予结构,元数据(如表模式)存储在metastore数据库中
Hive能和哪些版本的Hadoop共同工作:
Hive支持最新帆布的稳定版本以及之前的老版本,只要确保hadoop可执行文件在相应的路径下或设置HADOOP_HOME环境变量,就不必另行告诉Hive正在使用的哪个版本的hadoop
Hive的外壳环境
Hive的外壳环境是我们与Hive交互,发出HiveQL命令的主要方式 命令必须以分号结束
HiveQL一般是 大小写不敏感的
Hive可以使用-f选项运行在指定文件中的命令 ,比如:hive -f script.q,duiyu; 对于较短的脚本,可用-e选项在行内嵌入命令,此时不需要表示结束的分号 ,如:hive -e 'select * from dumy'
hive shell有用的特性: 使用dfs命令来访问Hadoop文件系统,使用!前缀来运行宿主操作系统的命令

在Hive的仓库目录中,表存储为目录,仓库的目录由选项hive.metastore.warehouse.dir指定,默认值为usr/hive/warehouse/records

配置Hive
Hive使用XML配置文件进行设置,配置文件为hive-site.xml,也可以使用如下方法:
1) 传递到--config选项参数给hive命令 ,可以通过这种方式 重新定义Hive查找hive-site.xml文件 ,如:hive --config /user/tom/dev/conf,这个选项指定的是包含配置文件的目录
2) 设置HIVE_CONF_DIR环境变量来指定配置文件的目录
这对于有(对应于多个集群)多个站点文件时很有用

Hive允许向hive命令传递-hiveconf选项来为单个会话设置属性,还可以在一个会话中 使用SET命令更改设置,这对于为某个特定的查询修改Hive或MapReduce作业设置非常有用 不带参数的SET命令会列出Hive所设置的所有属性及其取值(不包含hadoop属性),使用SET -v可以列出系统中所有属性

设置属性有个优先级层次:
Hive SET > -hiveconf >hive-site.xml > hive-default-xml > hadoop-site.xml(等价于core-site.xml、hdfs-site.xml与mapred-site.xml)

日志记录
可以在/tmp/$USER/hive.log找到Hive的错误日志
日志的配置放在conf/hive-log4j.properties中,或者使用命令:hive -hiveconf hive.root.logger=DEBUG,console


Hive服务
可以在运行时使用--service选项指明要使用哪种服务
一些有用的服务:
  • cli Hive的命令窗口(shell环境)
  • hiveserver 让Hive以提供Thrift服务的服务器形式运行,允许用不同的语言编写的客户端进行访问
  • hwi Hive的web接口(待测试
  • jar 与hadoop jar等价,这只运行类路径中同时包含hadoop和hive类java程序的简便方法
  • metastore 让metastore作为一个单独的进程运行

Metastore
metastore是Hive元数据的存放地 ,包括两部分: 服务和后台数据的存储
默认情况下,metastore服务和Hive服务运行在一个JVM中 ,它包含一个内嵌的以本地磁盘作为存储的Derby数据库实例

使用内嵌的metastore,一次只能为每个metastore打开一个服务,如果要支持多会话需要使用一个独立的数据库 ,如mysql

Hive三种模型
1)local模式
连接到In-memory的数据库Derby,一般用于Unit Test
2)单用户模式
通过网络连接到一个数据库中,是最常用的模式
3)远程服务器模式
在服务端启动MetaStoreServer,客户端利用Thrift协议通过MetaStoreServer访问元数据库

Hive和传统数据相比
写时模式:数据在写入时对照模式进行检查
读时模式: 对数据的验证并不在加载数据时验证,而在查询时验证
Hive被设计为用MapReduce操作hdfs数据,全表扫描是常态操作,而表更新则是通过把数据变换后放入新表实现的,hive不支持数据更新,但是支持insert into

Hive的索引分为两类:紧凑(compact)索引和位图(bitmap)索引
1) 紧凑索引存储每个值的hdfs块号 ,因此存储不会占用很多空间,且值被聚集存储于相近行的情况,索引仍然有效
2) 位图索引使用压缩的位集合来高效存储具有某个特征值的行 ,这种索引适用于具有较少可能值的列

HiveQL
sql与HiveQl比较
特性
sql
HiveQL
更新
insert update delete
insert
事务
支持
支持(表级和分区级)
索引
支持
支持
延迟
亚秒级
分钟级
数据类型
整数、浮点数、定点数、文本和二进制串,时间
整数,浮点数,布尔型,文本和二进制串,时间戳,数组,map,struct
函数
支持
支持
多表插入
不支持
支持
create table as select *
有些支持
支持
选择
SQL-92
FRom子句中只能有一个表或视图
连接
SQL-92
内连接,外链接,半连接,映射连接
子查询
任何子句
只能在FROM子句中
视图
可更新
只读
扩展点
用户定义函数
用户定义函数
存储过程
MapReduce脚本

数据类型:
简单类型:
tinyint,smallint,int,bigint float,double boolean,string,binary,timestamp
复杂类型:
array、map、struct

Hive的内置函数:数学与统计函数,字符串函数,日期函数,条件函数,聚集函数,处理XML和JSON函数
查询函数列表命令:show functions
了解某个特定函数的使用帮助,可以使用describe命令 describe function lengt h;

类型转换:Hive进行隐式类型转换,不会进行反向转换,除非用cast()操作
隐式类型转换规则
1) 所有整形可以转换为范围更广的类型
2) 所有整数类型,float和string类型都能隐式转换double类型;
3) tinyint,smallint,int都可以转换为float类型
4) Boolean类型不能转换为任何类型,timestamp可以隐式转换为string类型

表(托管表和外部表)
Hive的表在逻辑上由存储的数据和元数据组成 数据存储在hdfs上,元数据放在关系型数据库中
加载操作就是文件的移动或文件的重命名 ,因此他的速度很快, Hive不检查表目录中的文件是否符合表所声明的模式,我们通常通过查询为缺失字段返回的空值null才知道存在不匹配的行


外部表使用关键字external声明 Hive不会将文件移到自己得仓库目录 在定义时也不检查这个外部表的位置是否存在
如何选择使用哪种表:
如果所有的处理都由Hive完成,应该使用托管表 如果要用hive和其他工具来共同处理同一个数据集,则应该使用外部表
普通的用法: 把存储在hdfs(由其他进程创建)的初始数据集用作外部表进行使用,然后用hive的变换功能把数据移到托管的hive表

分区(partition)
Hive把表组织成分区,是一种 根据分区列的值对表进行粗略划分的机制,使用分区可以加快数据分片的查询速度
使用分区并不会影响大范围查询的执行:我们仍然可以查询跨多个分区的整个数据集

分区是在创建表的时候使用partitioned by子句定义的,partitioned by子句中定义的列是表中正式的列,成为分区列,但是数据文件并不包含这些列的值,因为它们源于目录

加载数据到分区表时,要显示的指定分区值
在文件系统级别, 分区只是表目录下嵌套的子目录
使用 show partitions tableName;命令可以查看tableName的分区

桶(bucket)
把表(分区)组织成桶的理由:
1) 获得更高的处理效率。桶为表加上了额外结构 ,具体而言, 连接两个在相同列上划分了桶的表,可以使用map端连接(map-site join)高效实现
2)使取样更高效
使用cluster by子句来指定划分桶所用的列和桶的个数

对于 map端连接连接, 首先 两个表以相同的方式划分桶 ,其次是 两个表桶的个数是倍数关系或相同

把Hive外生成的表加载到划分成桶的表中,则可以保证表中的数据已经划分成桶

想分成桶的表中填充数据,需要将hive.enforce.bucketing属性设置为true

物理上每个桶就是表(或分区)目录里的一个文件,事实上桶对应于MapReduce的输出文件分区:一个作业产生的桶和reduce任务个数相同

存储格式:
Hive从两个维度对表的存储进行管理, 行格式和文件格式
行格式的定义使用SerDe定义,Serde是序列化和反序列化的工具
默认的存储格式:分隔的文本
默认的行内分隔符是ASCII集合中的Control-A,集合元素默认的分隔符是Control-B,默认的map分隔符是Control-C
如果不确认Hive使用哪个字符作为某个嵌套结构的分隔符,可以使用如下命令:
create table nested as select array(array(1,2),array(3,4)) from dummy

二进制的存储格式 :顺序文件、Avro数据文件,RCFile
Hadoop的 顺序文件 格式是一种针对顺序和记录(键值对)的通用二进制格式,使用stored as sequencefile

使用顺序文件的一个主要优点就是它们支持可分割的压缩 ,如果你有一系列在Hive外产生的序列文件,则无需额外设置,Hive能读取它们

如果你想 用压缩顺序文件来存储Hive产生的表 ,需要设置几个相应的属性来使用压缩
hive.exec.compress.output=true;
mapred.output.compress=true;
mared.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec

RCFile表示按列记录文件 面向列的存储布局方式可以使一个查询跳过那些不必访问的列,对于那些只访问表中小部分行的查询比较有效 面向行的存储格式适合同时处理一行中很多列的情况 。如果空间足够,可以使用create table as select子句复制一个表,创建它的另一种存储格式,从而直观的比较负载两种存储格式在性能的差异


表的创建
– CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
– [(col_name data_type [COMMENT col_comment], ...)]
– [COMMENT table_comment]
– [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
– [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
– [SKEWED BY (col_name, col_name, ...) ON ([(col_value, col_value, ...), ...|col_value, col_value, ...]) (Note: only available starting with 0.10.0)]
– [ [ROW FORMAT row_format] [STORED AS file_format]
– | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] (Note: only available starting with 0.6.0) ]
– [LOCATION hdfs_path]
– [TBLPROPERTIES (property_name=property_value, ...)] (Note: only available starting with 0.6.0)
– [AS select_statement] (Note: this feature is only available starting with 0.5.0, and is not supported when creating external tables.)


示例:
create table stations (user string,nameint)
row format serde 'org.apache.hadoop.contrib.serde2.RegexSerde'
with serdeproperties( 'input.regex'='(\\d{6}) (\\d{5}) (.{29}) .*');
上面示例中用serde关键字和实现serde的java类完整类名来指定哪个SerDe,SerDe可以使用with SerdeProperties子句来设置额外的属性。

导入数据
1。load data [local] inpath 'path' into table table_name
2.
单表插入:insert into(overwrite) table_name select * from table_name2
多表插入:from source
insert into target_table_name1
select * group by ...
insert into target_table_name2
select * group by ...
... ...
insert into target_table_namen
select * group by ...
3.create table ... as select * from table_name

表的修改
重命名:alter table source rename to target
添加列:alter table target add columns (col string)
注: Hive不允许更新已有的记录,常用的做法是常见一个定义新列的新表,然后使用select语句把数据填充进去

表的删除:
drop table tablename;
如果要删除数据,保留表的定义(如mysql的delete或truncate),删除数据文件即可
如果该表为托管表,则它的数据和元数据都会删除;对于外部表而言,Hive不会碰数据,只删除元数据


MapReduce脚本:
使用transform、map和reduce子句可以在hive中调用外部脚本
示例:
1)使用Python脚本
add file /root/is_good_quality.py
from record2 select transform(col1,col2) using 'is_good_quality.py' as year,temperture

连接:
1)内连接
QL示例:
select sales.*,things.* from sales join things on (sales.id = things.id)
Hive只支持等值连接,意味着连接谓词中只能使用等号,不能在where子句中指定连接条件
在Hive中可以在连接谓词中使用and关键字分隔一系列表达式连接多个列
单个连接使用一个MapReduce作业实现,如果多个连接的连接条件使用了相同的列,那么平均每个连接可以用少于一个MapReduce作业来实现,在查询前可以使用explain关键字来查看Hive将为某个查询使用多少个MapReduce作业 ,如果要查询更详细的信息,可以在查询前使用explain extend
2)外连接(左外连接、右外连接、全连接)
left outer join 和right outer join和full outer join子句实现左外连接、右外连接、全连接
3)半连接
Hive并不支持In子查询,但可以用left semi join来达到相同的效果
示例:select * from things left semi join sales on (sales.id=things.id)
等价于select * from things where things.id in(select id from sales)
写left semi join查询时必须遵循一个限制:右表(sales)只能在on子句中出现,不能在select中引用右表
4)map连接
如果有一个连接表小到足以放入内存,Hive就可以把较小的表放入每个mapper的内存来指定操作,如果要使用map连接,需要在sql中使用C语言风格的注释,以给出提示:select /* mapjoin(things) */ sales.*,things.* from sales join things on (sales.id=things.id)

子查询
Hive对子查询的支持很有限,它 只允许子查询出现在select语句中的FRom子句中
示例:
select station,year, avg(max_temperture)
from (select station,year,max(temperture) max_temperture from records) mt group by station,year

视图
使用create view as select ...语句创建视图,
创建视图时并不执行查询,查询只是存储在metastore中,show tables命令的输出结果中包括视图,可以 使用describe extended view_name命令来查看某个视图的详细信息

UDF:
Hive中有三类UDF:
1)(普通)UDF:作用于单个数据行,且产生一个数据行作为输出
2)UDAF接收多个输入数据行,并产生一个输出数据行(像count和max函数)
3)UDTF用于单个输入数据行,且产生多个数据行


UDF实现和调用过程:
1.创建一个项目,编写一个Java类,继承org.apache.hadoop.hive.ql.exec.UDF类,类中实现evaluate
2.将项目导出为jar包,上传到服务器
3.添加jar包(在hive命令行里面执行):
add jar /root/NUDF.jar;
4.创建临时函数:
create temporary function getNation as 'cn.itcast.hive.udf.NationUDF';
5.SQL语句中调用:select id, name, getNation(nation) from beauty;
UDAF 自定义集函数
1)函数类继承org.apache.hadoop.hive.ql.exec.UDAF
2)org.apache.hadoop.hive.ql.exec.UDAFEvaluator(内部类 Evaluator
实现 UDAFEvaluator 接口)
3).Evaluator 需要实现 init、iterate、terminatePartial、merge、t
erminate 这几个函数
  • init():类似于构造函数,用于 UDAF 的初始化
  • iterate():接收传入的参数,并进行内部的轮转,返回 boolean
  • terminatePartial():无参数,其为 iterate 函数轮转结束后,返回轮转数据,类似于 hadoop 的 Combiner
  • merge():接收 terminatePartial 的返回结果,进行数据 merge 操作,其返回类型为 boolean
  • terminate():返回最终的聚集函数结果

你可能感兴趣的:(hive)