hive简介

hive是hadoop的一个重要子项目,利于mapreduce编程技术,实现部分sql语句,提供类SQL的编程接口。

hive是一个基于hadoop文件系统的数据仓库架构,它为数据仓库管理提供了许多功能:数据ETL,数据存储管理,大数据集的查询和分析能力。

由于hadoop是批处理系统,任务是高延迟的的,任务提交和处理过程会消耗一些时间成本,同样,即使hive处理的数据集很小,执行也会有延迟现象。

hive不提供数据排序和查询cache功能,不提供在线事务处理,也不提供实时查询和记录级别的更新,但hive能更好的处理不变的大规模数据集上的批量任务。

Hive组件

Hive的组件总体上可以分为:用户接口(UI)、驱动、编译器、元数据和执行引擎。

1)      对外的接口UI包括以下几种:命令行CLI,Web界面、JDBC/ODBC接口;

2)      驱动:接收用户提交的查询HQL;

3)     编译器:解析查询语句,执行语法分析,生成执行计划;

4)     元数据Metadata:存放系统的表、分区、列、列类型等所有信息,以及对应的HDFS文件信息等;

5)     执行引擎:执行执行计划,执行计划是一个有向无环图,执行引擎按照各个任务的依赖关系选择执行任务(Job)。

hive工作原理

1
Execute Query
 Hive接口,如命令行或Web UI发送查询驱动程序(任何数据库驱动程序,如JDBC,ODBC等)来执行。
2
Get Plan
在驱动程序帮助下查询编译器,分析查询检查语法和查询计划或查询的要求。
3
Get Metadata
编译器发送元数据请求到Metastore(任何数据库)。
4
Send Metadata
 Metastore发送元数据,以编译器的响应。
5
Send Plan
编译器检查要求,并重新发送计划给驱动程序。到此为止,查询解析和编译完成。
6
Execute Plan
驱动程序发送的执行计划到执行引擎。
7
Execute Job
在内部,执行作业的过程是一个MapReduce工作。执行引擎发送作业给JobTracker,在名称节点并把它分配作业到TaskTracker,这是在数据节点。
在这里,查询执行MapReduce工作。
7.1
Metadata Ops
与此同时,在执行时,执行引擎可以通过Metastore执行元数据操作。
8
Fetch Result
执行引擎接收来自数据节点的结果。
9
Send Results
执行引擎发送这些结果值给驱动程序。
10
Send Results
驱动程序将结果发送给Hive接口。
 

hive的数据存储

hive存储建立在hadoop文件系统的之上,没有专门的数据存储格式,也不能为数据建立索引,因此用户可以自由的组织hive中的表,只要在建表的时候告诉hive数据中列分隔符和行分隔符就可以解析数据了。

hive的有四类数据模型

Table,External Table,Partition,Bucket 也就是表,外部表,分区,桶

hive的表和关系数据库的表类似,但在hive中,每个表对应一个存储目录

hive中的每个分区都对应数据库中相应分区列的一个索引,分区的组织方式与关系数据库不同,hive表中的一个分区对应表下的一个目录,所有分区的数据都存储在对应的目录中。数据保存在分区中,删除分区,分区的元数据以及数据都将被删除,可以通过分区的方法减少每一次扫描总数据量,而不用进行整表扫描。

表 对于每一个表或者是分区,Hive可以进一步组织成,也就是说是更为细粒度的数据范围划分。Hive是针对某一列进行分。Hive采用对列值哈希,然后除以的个数求余的方式决定该条记录存放在哪个中。分的好处是可以获得更高的查询处理效率。使取样更高效。例如将id列分散在20个桶中,相对id列的值进行hash计算,对应的哈希值为0的写入分区的/customers/city=guangzhen/part-00000;对应哈希值为15,写入分区的目录/customers/city=guangzhen/part-00015,以此类推。在数据量足够大的情况下,分桶比分区,更高的查询效率。

外部表指向存在在hdfs中存在的数据,也可以创建分区。它和表在元数据组织上是相同的,存储不同:

创建表包括表的创建和表的加载两个步骤,数据加载过程中,实际数据会移动到数据仓库的目录中,之后数据的访问将会直接在数据仓库的目录中完成,删除表时,表的数据和元数据将会被同时删除。

外部表创建只有一个步骤,加载数据和创建表同事完成,实际数据存储在建表语句loacation指定的hdfs路径中,并不会移动到数据仓库目录中。删除一个外部表,仅仅删除元数据,表的数据不会被删除。

索引和分区最大的区别就是索引不分割数据库,分区分割数据库。索引其实就是拿额外的存储空间换查询时间,但分区已经将整个大数据库按照分区列拆分成多个小数据库了。一般分区能解决的,就不用索引。

分区和分桶最大的区别就是分桶随机分割数据库,分区是非随机分割数据库。

因为分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。

其次两者的另一个区别就是分桶是对应不同的文件(细粒度),分区是对应不同的文件夹(粗粒度)。

 hive的元数据管理

hive的元数据存储在RDBMS中,如mysql,derby中。

hive的安装配置

配置环境变量

修改配置文档hive-site.xml

主要配置项:

hive.metastore.warehouse.dir    hive的数据存储目录,指定的是hdfs上的位置

hive.exec.scratchdir   指定hive的数据临时文件目录

连接元数据数据库的配置,前提是需要将连接驱动程序拷贝到lib目录,需要配置连接字符串,驱动,数据库用户名,密码等参数。

hive错误日志,默认存储在/tmp/...

HQL

创建表

hive> create table test_table(id int,name string,level int,createtime int) partitioned by (city string) clustered by (level) sorted by (createtime) into 10 buckets
    > row format delimited     fields terminated by '001';
OK
Time taken: 1.37 seconds
hive> show create table test_table;
OK
CREATE TABLE `test_table`(
  `id` int,
  `name` string,
  `level` int,
  `createtime` int)
PARTITIONED BY (
  `city` string)
CLUSTERED BY (
  level)
SORTED BY (
  createtime ASC)
INTO 10 BUCKETS
ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
  'field.delim'='u00001',
  'serialization.format'='u00001')
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://localhost:9000/user/hive/warehouse/gamedw.db/test_table'
TBLPROPERTIES (
  'transient_lastDdlTime'='1528782424')
Time taken: 1.132 seconds, Fetched: 25 row(s)

修改表名

hive> alter table test_table rename to table_test;
OK
Time taken: 1.152 seconds

修改列名以及数据类型

hive> alter table table_test change level level bigint;
OK
Time taken: 0.773 seconds

修改列名以及类型并移动位置到id之后

hive> alter table table_test change level userlevel string after id;
OK
Time taken: 0.37 seconds
hive> show create table table_test;
OK
CREATE TABLE `table_test`(
  `id` string,
  `userlevel` string,
  `name` string,
  `createtime` string)
PARTITIONED BY (
  `city` string)
CLUSTERED BY (
  level)
SORTED BY (
  createtime ASC)
INTO 10 BUCKETS
ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
  'field.delim'='u00001',
  'serialization.format'='u00001')
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://localhost:9000/user/hive/warehouse/gamedw.db/table_test'
TBLPROPERTIES (
  'last_modified_by'='root',
  'last_modified_time'='1528783168',
  'transient_lastDdlTime'='1528783168')
Time taken: 0.257 seconds, Fetched: 27 row(s)

修改字段类型并调整到第一列

hive> alter table table_test change createtime regtime string first;
OK
Time taken: 0.404 seconds

列的改变只是改变了元数据,而不会改变实际数据。应该保证元数据与实际数据结构的一致性,不能随便更改数据类型或者字段位置。如果调整列的位置的数据类型与表定义的结构不符,调整位置会出错。因为报错,因此后面的调整字段位置的时候,首先将所有列调整为一致的数据类型。

增加列更新列

hive> alter table table_test add columns(sex int,plateid int);
OK
Time taken: 0.347 seconds

添加分区

hive> alter table table_test add partition(city='shenzhen')
    > ;
OK
Time taken: 1.19 seconds
hive> alter table table_test add partition(city='guangzhou')
    > ;
OK
Time taken: 0.367 seconds
hive> alter table table_test add partition(city='nanjing') partition(city='beijing');
OK
Time taken: 0.559 seconds

删除分区

hive> alter table table_test drop partition(city='beijing');
Dropped the partition city=beijing
OK
Time taken: 1.28 seconds

创建视图

hive> create view v_cust as select * from customers where city='shenzhen';
OK
Time taken: 0.355 seconds
hive> select * from v_cust;
OK
tianyongtao     1       50      shenzhen
wangwu  1       85      shenzhen
zhangsan        1       20      shenzhen
liuqin  0       56      shenzhen
wangwu  0       47      shenzhen
liuyang 1       32      shenzhen
Time taken: 0.77 seconds, Fetched: 6 row(s)

hive> show create table v_cust;
OK
CREATE VIEW `v_cust` AS select `customers`.`custname`, `customers`.`sex`, `customers`.`age`, `customers`.`city` from `gamedw`.`customers` where `customers`.`city`='shenzhen'
Time taken: 0.196 seconds, Fetched: 1 row(s)

索引

在指定列上创建索引,会产生一张额外的表,里面包括索引字段,以及该值所对应的HDFS文件路径,和该值在文件中的偏移量。

在执行索引字段查询的时候,首先生成一个额外的MR Job,根据对索引列的过滤条件,从索引表中过滤出索引列的值对应的HDFS文件路径以及偏移量,输出带hdfs一个文件中,然后根据这些文件的hdfs路径和偏移量筛选原始的input文件生成新的split,作为真个job的split,这样就可以不用全表扫描。

 

Hive的索引目的是提高Hive表指定列的查询速度。 没有索引时,类似'WHERE id = 10' 的查询,Hive会加载整张表或分区,然后处理所有的rows, 但是如果在字段id上面存在索引时,那么只会加载和处理文件的一部分。

创建索引

hive> create index ix_id on table table_test(id)as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' WITH DEFERRED REBUILD;
OK
Time taken: 0.859 seconds

查看索引

hive> SHOW FORMATTED INDEX ON table_test;
OK
idx_name        tab_name        col_names       idx_tab_name    idx_type        comment
idx_name                tab_name                col_names               idx_tab_name            idx_type                comment            
                                        
                                        
ix_id                   table_test              id                      gamedw__table_test_ix_id__      compact            
Time taken: 0.043 seconds, Fetched: 4 row(s)

hive> show tables like '*table_test*';
OK
tab_name
gamedw__table_test_ix_id__
table_test
Time taken: 0.091 seconds, Fetched: 2 row(s)

hive> drop index ix_id on table_test;
OK
Time taken: 2.875 seconds

插入数据:

hive> select * from table_test;
OK
table_test.regtime      table_test.id   table_test.userlevel    table_test.name table_test.sex  table_test.plateid      table_test.city
100     2000    300     20      20      50      shenzhen
100     200     300     20      20      50      shenzhen
100     200     300     20      20      50      shenzhen
100     2000    300     20      20      50      shenzhen
Time taken: 0.453 seconds, Fetched: 4 row(s)

创建索引并指定索引表名

hive> create index ix_id on table table_test(id)as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' WITH DEFERRED REBUILD in table table_index_test;
OK
Time taken: 0.333 seconds

hive> SHOW FORMATTED INDEX ON table_test;
OK
idx_name        tab_name        col_names       idx_tab_name    idx_type        comment
idx_name                tab_name                col_names               idx_tab_name            idx_type                comment            
                                        
                                        
ix_id                   table_test              id                      table_index_test        compact            
Time taken: 0.025 seconds, Fetched: 4 row(s)

填充索引数据:

hive> alter index ix_id on table_test rebuild;

索引表刷新数据可以指定分区,不指定则刷新整表,即整表重建索引。 如:alter index ix_id on table_test partition(city='shenzhen') rebuild;

然后可以在hdfs看到索引表的相关数据文件

索引表的基本包含几列:1. 源表的索引列;2. _bucketname hdfs中文件地址 3. 索引列在hdfs文件中的偏移量。

查看索引表数据:

select * from table_index_test;

.............................................

hive的优化

列裁剪 :查询需要的列,忽略其他列

分区裁剪:减少不必要的分区

join操作:将记录条数少的表或者子查询放在join操作符左边,join操作的reduce阶段,join操作左边的表内容会被加载到内存中,多个join的情况下,join的key相同,不管多少个表都会合并为一个mapreduce。如果join的条件不同,mapreduce的数据和join操作数目是对应的

map join:无需reduce操作就可以在map阶段全部完成。

group by:map端部分聚合;有数据倾斜(数据分布不均)时进行负载均衡

合并小文件

--------------------------

map端部分聚合

hive> set hive.map.aggr=true;

hive> set hive.groupby.mapaggr.checkinterval=10000; 设定map端进行聚合操作的条目数。

skews  [skju] 倾斜

负载均衡的设置: hive> set hive.groupby.skewindata=true;设置后,生成的查询计划会有两个mapreduce任务,在第一个mapreduce中,map的数据结果集合会随机分布到reduce中,对每个reduce做部分聚合操作并输出结果这样处理的结果是,相同的group by key 可能被分发到不同的reduce中,从而达到负载均衡的目的;第二个mapreduce任务再根据预处理的数据结果按照group by key 分布到reduce中,最终完成聚合操作

--------------------------

数据库中的Schema,为数据库对象的集合;

在设计Hive的schema的时候,需要考虑到存储、查询开销等,设计数据模型。

-------------------------------------

读时模式

Hive采用读时模式,在保存表数据时不对数据进行校验,而是在读数据时校验,不符合格式的数据设置为NULL,从而保证了大数据量的快速加载。

传统的关系数据采用写时模式,不符合格式的数据写不进去。
 
-------------------------------------
目前版本的Hive中没有提供类似存储过程的功能,使用Hive做数据开发时候,一般是将一段一段的HQL语句封装在Shell或者其他脚本中,然后以命令行的方式调用,完成一个业务或者一张报表的统计分析。
 
---------------------------------------------------
join:Hive 不支持所有非等值的连接
原文地址:https://www.cnblogs.com/playforever/p/9150283.html