1、什么是hive。(短小精悍的总结)
1.1:hive是基于hadoop的数据仓库。
1.2:hive可以使用类sql方言,对存储在hdfs上的数据进行分析和管理
2、hive的系统架构和核心组件。
2.1:核心模块:user interface、thrift server、driver、metastore、hadoop
user interface:主要cli即shell,次要jdbc\odbc,忽略hwi
thrift server:它用来进行可扩展且跨语言的服务的开发,hive集成了该服务,能让不同的编程语言调用hive
的接口。
driver:驱动组件包括Complier、Optimizer和Executor它的作用是将我们写的SQL语句进行解析、编译优化,
生成执行计划。
metastore:元数据服务组件,这个组件存储hive的元数据,hive的元数据存储在关系数据库里
hive支持的关系数据库有derby、mysql。元数据对于hive十分重要,因此把hive服务和metastore
服务独立出来,从而解耦hive服务和metastore服务,保证hive运行的健壮性。
hadoop:hive服务是基于hadoop。
3、hive的运行模式。
3.1:hive的运行模式包括本地,伪分布式,分布式。
本地:开发测试使用,原因速度快。使用方式:set hive.exec.mode.local.auto=true;
伪分布:上生产环境之前模拟测试,原因本地模式并不能展现生产环境的情况。
分布式:生产环境使用。
4、hive的存储形式。
hive的存储是基于hdfs之上的,它没有专门的存储格式。只要在创建表时指定行和列分隔符,hive就可以解析。
LINES TERMINATED BY '\t' :行分隔符
FIELDS TERMINATED BY '\001' :列分隔符
COLLECTION ITEMS TERMINATED BY '\002' :array,struct之间元素分隔符和map中的一组键值对分隔符
MAP KEYS TERMINATED BY '\003' :map中key与value之间的分隔符
5、hive命令的执行方式。
hive控制台:show databases;
linux控制台:显示执行信息:hive -e "show databases"
不显示执行信息:hive -S -e "show databases"
脚本:
在hive控制台下执行脚本:source xxx.sh
在linux控制台下执行脚本:hive -f xxx.sh 执行完毕后还停留在linux控制台下
hive -i xxx.sh 执行完毕后直接启动hive,进入hive控制台下
6、在hive控制台下的使用技巧。
与linux系统一样的命令补全操作:tab键
操作linux命令:!ls;
操作hdfs:dfs -ls /;
显示字段名称:set hive.cli.print.header=true;
7、hive的数据类型和文件格式。
hive的数据类型分为基本数据类型和集合数据类型。
基本数据类型:与传统数据一致。
微小int tinyint 1byte
小int smalint 2byte
int int 4byte
大int bigint 8byte
布尔 boolean true/false
单精度浮点 float
双精度浮点 double
字符串 string
时间戳 timestamp
粗体数据类型与java中的类型完全一致,并且也存在隐式的小类型转大类型。
集合数据类型:
struct struct<field1 string,field2 string> column.field1
map map<string,string> column['key1']
array array<string> column[0]
为什么会有集合数据类型?提高吞吐量,提升查询速度。
8.hive的读时模式。
写时模式:传统的关系型数据库在写入数据时候,会进行模式检查。
读时模式:而hive在写入数据时候不会进行模式检查,只有在读取数据时候才会进行模式检查。
9.HQL。
数据库========目录
表=======该目录下的子目录
数据库所在的目录是在hive.metastore.warehouse.dir所指定的顶级目录下,目录名称已.db结尾。
默认顶级目录:/user/hive/warehouse/
数据库:crxy=/user/hive/warehouse/crxy.db
表:student=/user/hive/warehouse/crxy.db/student/
DDL:
数据库
show databases;查看所有数据库
use crxy;使用数据库
create database crxy; 创建crxy数据库,默认在/user/hive/warehouse/目录下
create database crxy location "/dir1/"; 创建crxy数据库,在指定的/dir1/目录下
create database crxy with dbproperties("zhuozhe"="sunzheng","shijian"="2015-08-21","didian"="beijing");
给数据库添加属性信息。
describe database crxy;查看数据库信息
describe database extended crxy;查看更加完整数据库信息
drop database crxy;删除数据库,数据库中没有表,则删除,有则不删除。
drop database crxy cascade;强制删除,数据库中有表,也删除。
alter database crxy set dbproperties("zhuozhe"="lizhiming");修改数据库的属性信息,元数据信息不能修改。
表
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
创建 [外部] 表 [如果不存在] 数据库名.表名
(col_name data_type [COMMENT col_comment], ...)
(列名1 类型1 描述1,列名2 类型2 描述2,...)
[COMMENT table_comment]
表的描述信息
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
分区 (列名1 类型1 描述1,列名2 类型2 描述2,....)
[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, ...])
[STORED AS DIRECTORIES] ]
[ [ROW FORMAT row_format]
[STORED AS file_format] | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] ]
[LOCATION hdfs_path]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement] (Note: not supported when creating external tables.)
describe formatted student;格式化查看表的详细信息。
drop table student;删除表。
alter table student;修改表,只会修改元数据,数据本身不会修改。
alter table student rename to new_student;修改表名。
alter table student add partition (...) location "/";
10.hive的内部表,外部表,分区表,桶表。
创建内部表时,会将数据移动到数据仓库指向的路径;
创建外部表时,仅记录数据所在的路径,不对数据的位置做任何改变。
删除内部表的时候元数据和数据会被一起删除.
删除外部表的时候元数据会删除,数据不删除。
这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。创建外部表时候,需要添加关键字:EXTERNAL
分区表:对数据进行分类,不同类型的数据放到不同的目录下。分类的标准就是分区字段,可以一个,也可以多个。分区表的意义在于
优化查询。查询时尽量利用分区字段。如果不使用分区字段,就会全部扫描。关键字:PARTITIONED BY
桶表:数据加载到桶表时,会对字段取hash值,然后与桶的数量取模。把数据放到对应的文件中。桶表的抽样查询
假设一共有60个桶:select * from bucket_table tablesample(bucket 15 out of 20 on id)。
id代表以什么字段分桶。
20是除数,60是被除数,60\20=3,则一共取3个桶的数据。
15代表从哪个桶开始取,也就是取15,16,17这三个桶中的数据。
11.hive的存储格式。
答:TextFile,SequenceFile,RCFile
TextFile:存储空间消耗比较大,并且压缩的text 无法分割和合并 查询的效率最低,可以直接存储,加载数据的速度最高。
SequenceFile:存储空间消耗最大,压缩的文件可以分割和合并 查询效率高,需要通过text文件转化来加载。
rcfile:存储空间最小,查询的效率最高 ,需要通过text文件转化来加载,加载的速度最低。
12.Hive加载数据的方式有几种?
1、从本地文件系统中导入数据到Hive表。
load data [local] inpath "/usr/local/user" [overwrite] into table user;
2、从HDFS上导入数据到Hive表。
load data inpath "/user" into table user;
3、从别的表中查询出相应的数据并导入到Hive表中。
insert into table user2 select name,age from user; (追加)
insert overwrite table user2 select name,age from user; (覆盖)
4、在创建表的时候通过从别的表中查询出相应的记录并插入到所创建的表中。
create table user3 as select name,age from user;
13.hive的动态分区加载数据和静态分区加载数据。
静态分区static partition:手动输入数据分区名称。
动态分区dynamic partition:通过数据来判断数据分区名称。
开启动态分区:set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nostrict;
set hive.exec.max.dynamic.partitions.pernode=1000;
hive先获取select的最后两个位置的se.cnty和se.st参数值,然后将这两个值填写到Insert语句partition中的两
个country和state变量中,即动态分区是通过位置来对应分区值的。原始表select出来的值和输出partition的值
的关系仅仅是通过位置来确定的,和名字并没有关系,比如这里se.cnty和county的名称完全没有关系。
INSERT OVERWRITE TABLE employees
PARTITION (country, state)
SELECT ..., se.cnty, se.st
FROM staged_employees se;
只要位置正确,你可以混用动态分区和静态分区值设定。
INSERT OVERWRITE TABLE employees
PARTITION (country = 'china', state)
SELECT ..., se.cnty, se.st FROM staged_employees se
WHERE se.cnty = 'china';
14.hive的数据导出。
1、导出到本地文件系统。
insert overwrite local directory "/usr/local/user3" select * from user;
2、导出到hdfs系统上。
insert overwrite directory "/home/user/user3" select * from user;
3、导出到另一张Hive表中。(与导入一样)
insert into table user2 select name,age from user;
15.避免使用mapreduce。
不会使用mapreduce查询的方式:
select * from emp;查询所有字段。
sel select * from emp limit 123
select name,age from emp;查询单个字段。
select * from emp where country = 'china' and state='beijing';使用分区条件时。
16.hive join语句
inner join:hive不支持对inner join进行不等值链接。
select a.*,b.* from a_table a inner join b_table b on a.time <= b.time;
left outer join:left outer join操作符左边的符合where子句的所有记录会查出来,并与left outer join操作符右边的表按照on条
件进行连接,如果右边表没有符合on条件的记录时,那么右边表所选择的列的值会是NULL。
right outer join:right outer join操作符右边的符合where子句的所有记录会查出来,并与right outer join操作符左边的表按照on条
件进行连接,如果左边表没有符合on条件的记录时,那么左边表所选择的列的值会是NULL。
full outer join:返回所有表中符合where语句的所有记录,如果任意一张表指定的字段没有符合条件的值,那么就用NULL值替代。
left semi join:返回left semi join操作符左边的表记录,前提是其记录对于右边表满足on语句中的判定条件,相当于inner join的优化
版。
select a.name,a.age from a_table a left semi join b_table b on a.name = b.name and a.age = b.age;
join优化:
(1)当对多个表进行join连接时,如果每个on字句都使用相同的连接键的话,那么只会产生一个mr job。
(2)假设有3张表进行join操作,并且3张表的大小都不一样,a=20G、b=100G、c=1000G,那么应该将3张表的join关系由左到右
按照大小依次增加。
select a.*,b.*,c.*
from a_table a
inner join b_table b on a.id = b.id
inner join c_table c on a.id = c.id
(3)可以显示的指定哪个表时大表/*+streamtable(table_name)*/
17.order by & sort by & disteribute by & cluster by
order by:和传统sql一样,对最终的查询结果集进行全局排序。
sort by:是对局部结果集进行排序。
具体使用方法要看reduce阶段产生的reduce任务数量,如果只有1个reduce任务,那么使用order by和sort by效果是一样的。但
是如果reduce任务有多个,那么order by则对全部reduce任务的结果集进行整体排序。而sort by只对每个reduce任务进行局部排
序,因此可能会出现每个reduce任务输出的数据会有重叠。因为order by是对所有reduce的结果集进行整体排序,因此会消耗大量
时间,如果属性hive.mapred.mode的值为strict(严格模式),则hive强制要求必须使用limit限制,而如果时nonstrict则没限制
disteribute by:disteribute by通常与sort by联用。它相当于把结果集按照指定字段进行分类,分别放到不同的reduce中,然后在对分
类后的每个reduce做sort by排序,这样每个reduce任务输出的结果不会有重叠,并且全部有序。
select a.name,a.age,a.gender from a_table a disteribute by a.age sort by a.age,a.name;
注意:disteribute by必须在sort by之前定义。
cluster by:是对disteribute by与sort by连用时的一种简单写法。前提当disteribute by的值与sort by的值完全一致,并且是按照默
认的排序规则时。
select a.name,a.age,a.gender from a_table a cluster by a.age;
注意:其实就是联用情况下,把sort by中的a.name去掉。
18.hive视图 & 索引
视图的作用是降低查询的复杂度。视图只是一个定义,视图数据并不会存储到文件系统中。视图是只读的。
创建一个视图create view view_table as select * from user u inner join invest i on u.id=i.u_id where u.name="xxx";
通过视图进行查询select * from view_talbe;
删除一个视图drop view view_table;
索引的作用是减少mapreduce的输入数据量,不过因为建立索引需要消耗内存和计算时间,要谨慎设计。
创建索引:create index t1_index on table t1(name)as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
with deferred rebuild in table t1_index_table; as 是指定索引器。
重建索引:alter index t1_index on t1 rebuild;
显示索引:show formatted index on t1;
删除索引:drop index if exists t1_index on t1;
19.hive的设计模式
关于分区的设计:hdfs适合大文件存储,而不适合小文件存储。站在namenode内存和mapreduce任务处理的角度分析,分区的粒度过细可能
会导致存在大量的小文件,如果分区的层级目录很深,也会增加namenode的内存压力。同时会增加mapreduce所产生的
map任务过多导致执行效率下降。因此可以按照不同的时间粒度来确定适合大小的数据分区,同时按照时间的推移,分区
数量的增长应该是均匀的,并且每个分区下的文件大小应该是block块的大小的整数倍。已得到最优的数据吞吐量。
关于桶的设计:如果不能很好的确定分区的最优设计,可以考虑使用分桶表设计。
20.Hive的UDF
1、UDF函数可以直接应用于select语句,对查询结构做格式化处理后,再输出内容。
2、编写UDF函数的时候需要注意一下几点:
a)自定义UDF需要继承org.apache.hadoop.hive.ql.UDF。
b)需要实现evaluate函数,evaluate函数支持重载。
3、步骤
a)把程序打包放到目标机器上去;
b)进入hive客户端,添加jar包:hive>add jar /run/jar/udf_test.jar;
c)创建临时函数:hive>CREATE TEMPORARY FUNCTION add_example AS 'hive.udf.Add';
d)查询HQL语句:
SELECT add_example(8, 9) FROM scores;
SELECT add_example(scores.math, scores.art) FROM scores;
SELECT add_example(6, 7, 8, 6.8) FROM scores;
e)销毁临时函数:hive> DROP TEMPORARY FUNCTION add_example;
网友评论