Hive 是 FaceBook 开源的一款基于 Hadoop 数据仓库工具,它可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。
The Apache Hive ™ data warehouse software facilitates reading, writing, and managing large datasets residing in distributed storage using SQL 。
Hive 采用了类SQL 的查询语言 HQL(Hive Query Language),因此很容易将 Hive 理解为数据库。其实从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无类似之处。本文将从多个方面来阐述 Hive 和数据库的差异。数据库可以用在 Online 的应用中,但是Hive 是为数据仓库而设计的,清楚这一点,有助于从应用角度理解 Hive 的特性。
方向 | Hive | MySQL |
---|---|---|
应用方向 | 数仓 | Online |
查询语言 | HQL | SQL |
数据存储位置 | HDFS | 本地文件系统 |
数据更新 | 读多写少,无法修改 | 正常CRUD |
索引 | 无索引,暴力查询 | 各种索引 |
执行 | 底层MapReduce | 自己执行引擎 |
延迟 | 高延迟 | 低延迟 |
可扩展性 | 优秀扩展能力 | 扩展力有限 |
数据量 | 超大规模 | 小规模 |
Hive 底层是 MapReduce 计算框架,Hive 只是将通读性强且容易编程的SQL语句通过 Hive 软件转换成MapReduce 程序在集群上执行,Hive 可以看做 MapReduce 客户端。操作的数据还是存储在HDFS上的,而用户定义的表结构等元信息被存储到 MySQL 上了。以前要写八股文 MapReduce 程序,现在只需要HQL查询就可!
Hive整体框架
CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问hive)
HQL执行流程
不要把 Hive 想的多么神秘,你可以用简单的load方式将数据加载到创建的表里,也可以直接用hadoop指令将数据放入到指定目录,这两种方式都可以直接让你通过SQL查询到数据。
Join流程
group by 流程
distinct 流程
有时想要同时显示聚集前后的数据,这时引入了窗口函数,在SQL处理中,窗口函数都是最后一步执行
,而且仅位于 Order by 字句之前。
name,orderdate,cost
jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68
neil,2017-05-10,12
mart,2017-04-11,75
neil,2017-06-12,80
mart,2017-04-13,94
建表 导数据
create table business(
name string,
orderdate string,
cost int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
load data local inpath "/opt/module/datas/business.txt" into table business;
相关函数说明
上面写 over 里面,下面写 over 前面。
第
n 行数据第
n 行数据select name,count(*) over() from business where substring(orderdate,1,7) = '2017-04' group by name;
结果:
mart 2
jack 2
select name,orderdate,cost,sum(cost) over(partition by month(orderdate))
from business;
解释:按照月划分数据 然后统计这个月的cost总和
jack 2017-01-01 10 205
jack 2017-01-08 55 205
tony 2017-01-07 50 205
jack 2017-01-05 46 205
tony 2017-01-04 29 205
tony 2017-01-02 15 205
jack 2017-02-03 23 23
mart 2017-04-13 94 341
jack 2017-04-06 42 341
mart 2017-04-11 75 341
mart 2017-04-09 68 341
mart 2017-04-08 62 341
neil 2017-05-10 12 12
neil 2017-06-12 80 80
select name,orderdate,cost,
lag(orderdate,1,'defaulttime') over(partition by name order by orderdate ) as time1,
lag(orderdate,2,'defaulttime') over (partition by name order by orderdate) as time2 from business;
结果 :
姓名 日期 价格 前一天日期 前两天日期
jack 2017-01-01 10 defaulttime defaulttime
jack 2017-01-05 46 2017-01-01 defaulttime
jack 2017-01-08 55 2017-01-05 2017-01-01
jack 2017-02-03 23 2017-01-08 2017-01-05
jack 2017-04-06 42 2017-02-03 2017-01-08
mart 2017-04-08 62 defaulttime defaulttime
mart 2017-04-09 68 2017-04-08 defaulttime
mart 2017-04-11 75 2017-04-09 2017-04-08
mart 2017-04-13 94 2017-04-11 2017-04-09
neil 2017-05-10 12 defaulttime defaulttime
neil 2017-06-12 80 2017-05-10 defaulttime
tony 2017-01-02 15 defaulttime defaulttime
tony 2017-01-04 29 2017-01-02 defaulttime
tony 2017-01-07 50 2017-01-04 2017-01-02
select * from (
select name,orderdate,cost, ntile(5) over(order by orderdate) sorted from business ) t where sorted = 1;
结果 :
jack 2017-01-01 10 1
tony 2017-01-02 15 1
tony 2017-01-04 29 1
jack 2017-01-05 46 2
tony 2017-01-07 50 2
jack 2017-01-08 55 2
jack 2017-02-03 23 3
jack 2017-04-06 42 3
mart 2017-04-08 62 3
mart 2017-04-09 68 4
mart 2017-04-11 75 4
mart 2017-04-13 94 4
neil 2017-05-10 12 5
neil 2017-06-12 80 5
以下实验均关注最后一列
1. 所有行相加
select name,orderdate,cost,sum(cost) over() as sample1 from business;
结果 :
mart 2017-04-13 94 661
neil 2017-06-12 80 661
mart 2017-04-11 75 661
neil 2017-05-10 12 661
mart 2017-04-09 68 661
2. 按name分组,组内数据相加
select name,orderdate,cost,sum(cost) over(partition by name) as sample2
from business;
结果 :
jack 2017-01-05 46 176
jack 2017-01-08 55 176
jack 2017-01-01 10 176
jack 2017-04-06 42 176
jack 2017-02-03 23 176
...
tony 2017-01-04 29 94
tony 2017-01-02 15 94
tony 2017-01-07 50 94
3. 按name分组,组内数据累加
select name,orderdate,cost,
sum(cost) over(partition by name order by orderdate) as sample3
from business;
跟下面类似
select name,orderdate,cost,
sum(cost) over(distribute by name sort by orderdate) as sample3
from business;
jack 2017-01-01 10 10
jack 2017-01-05 46 56
jack 2017-01-08 55 111
jack 2017-02-03 23 134
jack 2017-04-06 42 176
...
4. 和sample3一样,由起点到当前行的聚合
select name,orderdate,cost,
sum(cost) over(partition by name order by orderdate rows
between UNBOUNDED PRECEDING and current row ) as sample4
from business;
结果 :
jack 2017-01-01 10 10
jack 2017-01-05 46 56
jack 2017-01-08 55 111
jack 2017-02-03 23 134
jack 2017-04-06 42 176
...
5. 当前行和前面一行做聚合
select name,orderdate,cost,
sum(cost) over(partition by name order by orderdate rows
between 1 PRECEDING and current row) as sample5
from business;
结果 :
jack 2017-01-01 10 10
jack 2017-01-05 46 56 = 46 + 10
jack 2017-01-08 55 101 = 44 + 46
jack 2017-02-03 23 78 = 23 + 55
jack 2017-04-06 42 65 = 42 + 23
...
tony 2017-01-02 15 15
tony 2017-01-04 29 44
tony 2017-01-07 50 79
6. 当前行和前边一行及后面一行
select name,orderdate,cost,
sum(cost) over(partition by name order by orderdate rows
between 1 PRECEDING AND 1 FOLLOWING ) as sample6
from business;
结果 :
jack 2017-01-01 10 56 = 10 + 46
jack 2017-01-05 46 111 = 46 + 10 + 55
jack 2017-01-08 55 124 = 55 + 46 + 23
jack 2017-02-03 23 120 = 23 + 55 + 42
jack 2017-04-06 42 65 = 42 + 23
...
tony 2017-01-02 15 44
tony 2017-01-04 29 94
tony 2017-01-07 50 79
7. 当前行及后面所有行
select name,orderdate,cost,sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample7 from business;
结果 :
jack 2017-01-01 10 176 = 10 + 46 + 55 + 23 + 42
jack 2017-01-05 46 166 = 46 + 55 + 23 + 42
jack 2017-01-08 55 120 = 55 + 23 + 42
jack 2017-02-03 23 65 = 23 + 42
jack 2017-04-06 42 42 = 42
mart 2017-04-08 62 299
mart 2017-04-09 68 237
mart 2017-04-11 75 169
mart 2017-04-13 94 94
neil 2017-05-10 12 92
neil 2017-06-12 80 80
tony 2017-01-02 15 94
tony 2017-01-04 29 79
tony 2017-01-07 50 50
函数说明
rank():排序相同时会重复,总数不会变 dense_rank():排序相同时会重复,总数会减少 row_number():会根据顺序计算
select name,subject,score,
rank() over(partition by subject order by score desc) rp,
dense_rank() over(partition by subject order by score desc) drp,
row_number() over(partition by subject order by score desc) rmp
from score;
结果 :
name subject score rp drp rmp
孙悟空 数学 95 1 1 1
宋宋 数学 86 2 2 2
婷婷 数学 85 3 3 3
大海 数学 56 4 4 4
宋宋 英语 84 1 1 1
大海 英语 84 1 1 2
婷婷 英语 78 3(跳过2)2 3
孙悟空 英语 68 4 3(总数少) 4
大海 语文 94 1 1 1
孙悟空 语文 87 2 2 2
婷婷 语文 65 3 3 3
宋宋 语文 64 4 4 4
返回输入字符串
连接后
的结果,支持任意个输入字符串;
将hive一列中复杂的array或者map结构拆分成多行。
如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么 Hive 解析器会将 Join 操作转换成 Common Join,也就是在Reduce阶段完成join。容易发生数据倾斜。可以用 MapJoin 把小表全部加载到内存在map 端进行 join,避免 reducer 处理。
列处理:在SELECT时只拿需要的列,尽量使用分区过滤,少用SELECT *。 行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在 Where后面,那么就会先全表关联,之后再过滤。
如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费 。而且,同时可执行的map数是受限的。此时我们就应该减少map数量。
严格模式 strict 下会有以下特点:
在不影响最终业务逻辑前提下,手动开启 set hive.map.aggr=true;
设置map端输出中间结果压缩,加速网络传输。
在Map执行前合并小文件,减少Map数,CombineHiveInputFormat 具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
数据分布不平衡,某些地方特别多,某些地方又特别少,导致的在处理数据的时候,有些很快就处理完了,而有些又迟迟未能处理完,导致整体任务最终迟迟无法完成,这种现象就是数据倾斜。
表外
字段,需要指定字段类型关键字
partitioned by(partition_name string)声明较粗
分桶逻辑:对分桶字段求哈希值,用哈希值与分桶的数量取余决定数据放到哪个桶里。
表内
字段,已经知道字段类型,不需要再指定。更细
粒度的划分、管理数据,可以对表进行先分区再分桶的划分策略视图是一种使用查询语句定义的虚拟表,是数据的一种逻辑结构,创建视图时不会把视图存储到磁盘上,定义视图的查询语句只有在执行视图的语句时才会被执行。视图是只读的,不能向视图中插入或是加载数据
Hive支持在表中建立索引。但是索引需要额外的存储空间,因此在创建索引时需要考虑索引的必要性。
Hive不支持直接使用 DROP TABLE 语句删除索引表。如果创建索引的表被删除了,则其对应的索引和索引表也会被删除;如果表的某个分区被删除了,则该分区对应的分区索引也会被删除。
如果Hive中没有特别指定,则默认创建的表都是管理表,也称内部表。由Hive负责管理表中的数据,管理表不共享数据。删除管理表时,会删除管理表中的数据和元数据信息。
当一份数据需要被共享时,可以创建一个外部表指向这份数据。删除该表并不会删除掉原始数据,删除的是表的元数据。
源网侵删