赞
踩
hive
Hive是建立在hadoop之上的数据仓库的基础架构。它提供了一些工具,可以用来进行数据提取、转化、加载(ETL),这是一种储存、查询和分析储存在hadoop中的大规模数据的机制。Hive 定义了简单的类 SQL 查询语言,称为 HQL,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作。
支持创建索引,优化数据查询。
不同的储存类型,例如:纯文本文件、Hbase中的文件。
将原数据保存在关系型数据库中。
可以将数据储存在HDFS分布式文件系统中
内置大量的用户函数UDF来操作时间、字符串、和其他的数据挖掘工具、支持用户扩展UDF函数来完成内置函数无法完成的复杂操作。
类查询方式,将sql查询查询转为mapReduce的job,在hadoop集群上执行。
用户接口:
用户接口主要分为:CLI、Clinet、WUI,其中最常用的是Cli命令行的模式,Cli启动的时候会启动一个Hive的副本,Client是hive的客户端,用户连接至Hive Server.在启动Client的时候,需要指出Hive server所在的节点。WUI是通过浏览器访问的方式访问Hive。
元数据储存:
Hive将元数据储存在数据库中,如MySql、derby。hive的元数据包括表的名字、表的列以及分区及其属性,表的属性包括是否是否外部表。表的数据所在的目录等。
解释器、编译器、优化器、执行器
解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划储存在HDFS中并随后由MapReduce执行。
Hadoop:
hive的数据储存在HDFS中,大部分的查询由MR完成,(不包含*的查询,比如select * from talename)
hive数据仓库和数据库的区别:
数据库中储存的数据可以对随意其进行增删改查操作
数据库中储存的数据是随用户的操作而动态变化的
数据库中的数据储存容量是有限的,当数据库中的数据过于庞大时,查询效率会下降。
数据仓库中的数据存储的是静态的历史数据,我能只能对数据进行添加和查询操作。
数据仓库的容量是很大的,数据仓库中的数据是基于HDFS的,而将数据的元数据储存在metastore中的,基于内存查询的,当client客户端进行查询数据时会很快将数据返回
hive数据仓库会和hbase进行整合,hive将成为client的角色用于储存数据的元信息,hbase进行储存数据,hive基于内存的数据处理方式将有很快的效率。
一般MetaStore一般是由MYSQL或者Derby来承担,一般储存的是表名,列名,和表的一些属性,是否是外部表等。Derby数据库是Hive自带的Apache的一个数据库,一般用于测试。
在大量的数据面前,我们无法对特定时间的数据进行查询,或者查看某一个时间点的数据库中数据的变化,这些我们都是无法操作的,而引入时间拉链表,可以解决这些无法执行的操作,这里的时间拉链表相当于对数据进行操作时一段时间的“快照”,也可以理解为历史记录。
首先启动hiveserver2
要在hadoop的core-site.xml添加属性:
hadoop.proxyuser.root.groups
hadoop.proxyuser.root.hosts
执行命令或者重启hadoop集群
bin/hdfs dfsadmin -fs hdfs://node01:8020 -refreshSuperUserGroupsConfiguration
bin/hdfs dfsadmin -fs hdfs://node02:8020 -refreshSuperUserGroupsConfiguration
Beeline要与hiveserver2配合使用
客户通过beeline两种方式连接到hive:
beeline -u jdbc:hive2://node:10000/default -n root
-默认用户名、密码不验证
beeline
!connect jdbc:hive2//<host>:<port>/<db> root 123
1.存量、流量、增量
1)存量:系统在某一点时所保存的所有数量
2)流量:某一个时间点上流入、流出系统的数量
3)增量:某一个时间段内,系统中数据量的变化
增量=输入量-输出量
4)本期期末储存量=上期期末存量+本期增量
2.拉链表
1)记录一个实物从开始当当前所有的状态变化
2)拉链表每次上报的是历史记录的最终状态,是记录在当前时刻的历史总量。
3)存量是某一时刻的总量,存量一般设计成拉链表。(工作中常用月报、日报)
4)流量和存量的区别:流量是增量,存量是总量。
5)拉链表和增量表的表结构一般是一样的。
时间拉链表既能够反应数据的历史状态,有可以最大程度地节省储存空间。
hive中对数据的分区是对数据在HDFS上储存是分别创建不同的目录,即在不同的目录中储存不同数据,比如将不同日期内的数据进行储存的时候,在HDFS上创建不同日期的目录,用于储存对应不同日期内的数据。
对不同的数据进行分区后如果在对不同的日期中查询时,可以根据需求再不同的日期目录下进行查询,这样既节省了了查询时间又减少了磁盘读写的IO操作
如果对数据不进行分区,那么当查询数据时,都会对数据进行全量查询,每次全量查询不光浪费时间还增加了IO量
分区优点:
对不同的数据进行分区后如果在对不同的日期中查询时,可以根据需求再不同的日期目录下进行查询,这样既节省了了查询时间又减少了磁盘读写的IO操作
如果对数据不进行分区,那么当查询数据时,都会对数据进行全量查询,每次全量查询不光浪费时间还增加了IO量
分区表:
create table psn3(
id int,
name string,
address array<string>,
hobby map<string,string>
)
partitioned by (age=20,age=10)
row format delimited
fields terminated by ','
collection items
map keys terminated by ':'
create table psn4(
id int,
name string,
address array<string>,
hobby map<string,string>
)
partitioned by (age,int,date Date)
row format delimited
fields terminated by ','
collection items
map keys terminated by ':'
Hive删除分区语法:
alter table table_name drop partition_spec,partition_spec...
partition_spec:
: (partition_column = partition_col_value, partition_column = partition_col_value, ...)
用户可以用 alter table drop partition 来删除分区。
内部表中、对应分区的元数据和数据将被一并删除。
例:
alter table day_hour_table drop partition (dt='2008-08-08', hour='09')
对于每一个表或者分区,hive可以进一步组织成桶,也就是说更为细粒度的数据划分,可以在分区的基础上在进行分桶,分桶的规则是,将一组数据,例如Day01里有北京、上海、广州的数据。Day02中同样有北京上海广州的数据,现在按照日期进行分区,分区后:day01->{北京,上海,广州},day02->{北京,上海,广州},如果在分区内进行查询北京的数据那么还是要进行全量的遍历,那么现在进行对数据对每个分区内的数据进行分桶,对分区中的数据分别对北京上海广州的hashCode哈希值进行对桶数(这里默认是3),则将会得到北京、上海、广州的数据分别对应一个不同的值,则将对应的数据放入对应的同种,这样在查询不同城市的数据时,只需找对应的桶就行了,无序进行全量遍历,当然这里的分区分桶都是根据实际需求的。即工作中根据经常查询的字段我们可以进行分区或者分桶,进行数据的查询。
分桶的实质就是对分桶表的字段做哈希计算,然后存放到对应文件中,所以如果原有数据没有按key哈希,在存放数据插入分桶的时候进行hash,也就是说在向分桶表中插入数据的时候必然要指定一次MapReduce。这也决定了分桶表中的数据只能从所查询的结果集中查询插入的方式进行插入数据。
set hive.enforce.bucketing=true;
默认:false
开启自动分桶后mr会根据bucket的个数自动创建reducer task的个数。(用户也可以自动设置桶的个数:mapered.reduce.task但分桶时不推荐使用)
注意:一次作业产生的桶的数量(文件的数量)和task的数量是一致的。
create table psn1(
id int,
name string,
age int
)
row format delimited
fields terminated by ','
//加载数据
load data local inpath '/root/data3' into table psn1;
create table psn2(
id int,
name string,
age int
)
clustered by (age) into 4 buckets
row format delimited
fields terminated by ',';
加载分桶数据:
from psn1
insert into psn2
select id,name,age
tablesample是抽样语句,语法:tablesample(backet x outof y)
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了64份,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据。
x表示从哪个bucket开始抽取。例如,table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据
hive另外一种按照抽样百分比进行抽样的方式,该种方式基于行数,按照输入路径下的数据块的百分比进行抽样。
这种抽样的最小单元是一个hdfs数据块,如果表的数据大小小于普通块大小128M,将返回所有行。
数据分桶存在的一些缺陷:
如果通过数据文件LOAD 到分桶表中,会存在额外的MR负担。
实际生产中分桶策略使用频率较低,更常见的还是使用数据分区。
Hive SerDe -Serializer and Deserializer
-SerDe 用于做序列化和反序列化
-构建在数据储存和执行引擎之间,对两者实现解耦。
-Hive通过row format delimited 以及SerDe进行读写。
Hive正则匹配
CREATE TABLE logtbl (
host STRING,
identity STRING,
t_user STRING,
time STRING,
request STRING,
referer STRING,
agent STRING)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)"
)
stored as textfile;
序列化是对象转换为字节序列的过程。 反序列化是字节序列恢复为对象的过程。 对象的序列化主要有两种用途:对象的持久化,即把对象转换成字节序列后保存到文件中;对象数据的网络传送。 除了上面两点, hive的序列化的作用还包括:Hive的反序列化是对key/value反序列化成hive table的每个列的值。Hive可以方便的将数据加载到表中而不需要对数据进行转换,这样在处理海量数据时可以节省大量的时间。
SerDe说明hive如何去处理一条记录,包括Serialize/Deserilize两个功能, Serialize把hive使用的java object转换成能写入hdfs的字节序列,或者其他系统能识别的流文件。Deserilize把字符串或者二进制流转换成hive能识别的java object对象。比如:select语句会用到Serialize对象, 把hdfs数据解析出来;insert语句会使用Deserilize,数据写入hdfs系统,需要把数据序列化。
—内部表和外部表的区别:
1.创建: 外部表需要指定一个储存路径
内部表不需要,储存在默认路径中
2.删除 内部表会把元数据和数据文件全部删除
外部表只删除元数据,不删除数据
使用场景:
如果hdfs中不存在任何已有的数据,表和数据都是新插入的,则是由内部表
如果hdfs中已经在某一个目录汇中有储存的数据,则使用外部表使用
reate table psn
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':'
create external table psn2
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':'
location '/usr/';
create table tbl1
(
id int,
name string,
likes array<string>,
address map<string,string>
)
partitioned by (age int)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':';
//向静态分区中导入数据:
load data local inpath '/root/data' into table tbl1 partition (age=10)
create table tb2
(
id int,
name string,
likes array<string>,
address map<string,string>
)
partitioned by (age int,gender string)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':';
添加分区的值(不是添加分区)
alter table psn6 add partition(int name)
只能添加已经有的分区的值
//删除分区
alter table tablename drop partition(age=12)
//删除age=12的分区
load data local inpath '/data' insert into psn2
local:从本地将数据复制一份上传到表中
load data inpath '/data' insert into psn2
将HDFS中的数据移动过来,而不是复制了。
from tablename
insert into newtablename
select *
create table psn8 like psn7;
create table psn9 as select * from psn7;
权限操作
将角色授予某个用户、角色:
GRANT role_name [, role_name] ...
TO principal_specification [, principal_specification] ...
[ WITH ADMIN OPTION ];
principal_specification
: USER user
| ROLE role
移除某个用户、角色的角色:
REVOKE [ADMIN OPTION FOR] role_name [, role_name] …
FROM principal_specification [, principal_specification] … ;
revoke [admin option for] role_name [,role_name] … from principal_specification [,principal_specification…]
查看授予某个用户、角色的角色列表
show role grant (user|role) principal_name;
查看属于某种角色的用户、角色列表
show principals role_name;
hive -e "select * from psn1"
还可以执行多条sql
hive -e "select * from psn1;select * from psn2"
执行查询并进行重定向
hive -e "select * from psn1" >/root/aaa.txt
//语法
hive -e 'sql语句'
--执行文件中的sql
vim sql
select * from psn2;
//执行sql文件
hive -f sql
创建表
创建表
create table psn3(
id int,
name string,
hobby array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':';
//加载数据
load data local inpath '/root/data1' into table psn3;
//lateral view语法
select count(distinct(myCol1)), count(distinct(myCol2)) from psn3
LATERAL VIEW explode(hobby) myTable1 AS myCol1
LATERAL VIEW explode(address) myTable2 AS myCol2, myCol3;
lateral view的作用:
1.结束了explode的局限性,explode(column)只能处理单一的列
2.和explode结合实用扩展了实用性
select id,myCol1,myCol2 from psn3
lateral view explode(hobby) myTable1 as myCol1
lateral view explode(address) myTable2 as myCol2,myCol3;
-### ---------索引------------
目的:优化查询以及检索性能
创建索引:
create index t1_indx on table psn2(name)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
with deferred rebuild
in table t1_index_table;
as 指定索引器:
in table:指定索引表,若不指定,默认生成在default_psn2_index表中
create index t2_index on table psn2(name)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild;
//查看索引:
show index on tablename;
//重建索引(必须建立索引后才能使用,向索引表中插入数据):
alter index t1_indx on psn2 rebuild;
//删除索引表:
drop index if exists t1_index on psn2;
drop index t1_index on psn2;
思想:把hive sql转换成mapreduce去优化。
理论上hive中的sql语句都可以转换位MapReudce去执行。
设置参数
Set hive.fetch.task.conversion=none/more
hive中做了sql的优化,hive对一下hql语句不会执行mapreduce语句
select仅查询本表字段
select * from tablename;
where仅对本表字段做条件过滤
select * form tablename where …;
explain [extended] query
例子:explain extended select count(*) from psn2;
通过设置参数开启并行模式
set hive.exec.parallel=true;
注意:
hive.exec.parallel.thread.number
一次sql计算中允许并行执行的MR job的最大值,默认是8
设置一下参数开启严格模式
(默认为:nonstrict非严格模式)
-查询限制
1)对于分区表,必须添加where对于分区字段的条件过滤
2)order by 语句必须包含limited输出闲置
3)限制笛卡尔积的查询
order by:对于查询结果做全排序,只允许一个reduce进行处理。将数据量较大时谨慎使用,最后不用,严格模式下结合limit来使用
Sort by : Hive中指定了sort by,那么在每个reducer端都会做排序,也就是说保证了局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)。
Distribute by分区排序,经常和sort by 结合使用,控制map输出在reducer上是如何划分的。
Cluster by:相当于sort by +distribute by 几乎不用
(cluster by 不能通过asc,desc的方式制定排序规则)
可通过distribute by column sort by column asc|desc的方式
join计算时,将小表(驱动表)放在join的左边
map join:在map端完成join.
两种实现方式:
1)sql方式 ,在sql语句中添加map join 标记(mapjoin hint)
语法:
select /+MAPJOIN(smalltable)/ smallTable.key ,bigTable.value
from smallTable
join bigTable on smallTable.key=bigTable.key;
2.开启自动的mapjoin
通过修改以下配置启动自动的mapjoin
通过修改以下配置启用自动的mapjoin:
set hive.auto.convert.join=true;
该参数为true时,两份数据时,如果有一份数据比较小,会将小数据全部加载到内存,按照关键字进行索引。大的数据文件 作为map的输入文件,对于map的每一对输入,都能够方便地和已经加载到内存中的小文件进行连接,将连接好的的文件按key输出。
这种方法要使用hadoop中的DistributedCache把小数据文件分散到不同的节点上。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。