一 Hive
的架构
Hive架构图示
二 Hive
和数据库比较
1️⃣相同点 : 拥有类似的查询语言;
2️⃣不同点 :
1. 数据存储位置 :Hive
存储在HDFS
;数据库将数据保存在块设备或者本地文件系统中;
2. 数据更新 :Hive
中不建议对数据的改写而数据库中的数据通常是需要经常进行修改的;
3. 执行延迟 : 数据规模较小的情况下Hive
执行延迟较高数据库的执行延迟较低;当数据规模大到超过数据库的处理能力的时候,Hive
的并行计算显然能体现出优势;
4. 数据规模 :Hive
支持很大规模的数据计算,数据库可以支持的数据规模较小;
三 内部表和外部表
1️⃣ 内部表 : 当我们删除一个管理表时,
Hive
也会删除这个表中数据;内部表不适合和其他工具共享数据;
2️⃣ 外部表 : 删除该表并不会删除掉原始数据,删除的是表的元数据;
四 4
个By
区别
1️⃣
Sort By
: 分区内有序;
2️⃣Order By
: 全局排序,只有一个Reducer
;
3️⃣Distrbute By
: 类似MR
中Partition
进行分区,结合sort by
使用;
4️⃣Cluster By
: 当Distribute by
和Sorts by
字段相同时可以使用Cluster by
方式;Cluster by
除了具有Distribute by
的功能外还兼具Sort by
的功能;但是排序只能是升序排序不能指定排序规则为ASC
或者DESC
;
五 窗口函数
RANK()
: 排序相同时会重复总数不会变;DENSE_RANK()
: 排序相同时会重复总数会减少;ROW_NUMBER()
: 会根据顺序计算;OVER()
: 指定分析函数工作的数据窗口大小这个数据窗口大小可能会随着行的变化而变化;CURRENT ROW
: 当前行;n PRECEDING
: 往前n
行数据;n FOLLOWING
: 往后n
行数据;UNBOUNDED
: 起点UNBOUNDED PRECEDING
表示从前面的起点,UNBOUNDED FOLLOWING
表示到后面的终点;LAG(col,n)
: 往前第n
行数据;LEAD(col,n)
: 往后第n
行数据;NTILE(n)
: 把有序分区中的行分发到指定数据的组中各个组有编号,编号从1
开始对于每一行NTILE
返回此行所属的组的编号注意n
必须为int
类型;
六 自定义UDF
& UDTF
1️⃣ 是否自定义过
UDF
和UDTF
函数?
自定义过;
2️⃣ 用他们处理了什么问题?
用UDF
函数解析公共字段,用UDTF
函数解析事件字段;
3️⃣ 自定义步骤?
继承自GenericUDTF
,重写3
个方法 :initialize
(自定义输出的列名和类型),process
(将结果返回forward(result)
),close
;
4️⃣ 为什么要自定义UDF / UDTF
?
自定义函数可以自己埋点Log
打印日志,出错或者数据异常的时候方便调试;
七 Hive
优化
1️⃣ MapJoin
如果不指定MapJoin
或者不符合MapJoin
的条件,那么Hive
解析器会将Join
操作转换成Common Join
,即 : 在Reduce
阶段完成join
,容易发生数据倾斜;可以用MapJoin
把小表全部加载到内存在map
端进行join
避免reducer
处理;
2️⃣ 行列过滤
列处理 : 在SELECT
中,只拿需要的列如果有尽量使用分区过滤少用SELECT *
;
CONCAT(string A/col, string B/col…)
: 返回输入字符串连接后的结果支持任意个输入字符串;
CONCAT_WS(separator, str1, str2,...)
: 它是一个特殊形式的CONCAT()
第一个参数剩余参数间的分隔符,分隔符可以是与剩余参数一样的字符串;如果分隔符是NULL
返回值也将为NULL
;这个函数会跳过分隔符参数后的任何NULL
和空字符串;分隔符将被加到被连接的字符串之间;
COLLECT_SET(col)
: 函数只接受基本数据类型它的主要作用是将某字段的值进行去重汇总产生array
类型字段;
3️⃣ 行处理 : 在分区剪裁中当使用外关联时,如果将副表的过滤条件写在Where
后面那么就会先全表关联之后再过滤;
4️⃣ 函数说明
EXPLODE(col)
: 将hive
一列中复杂的array
或者map
结构拆分成多行;
LATERAL VIEW
:
用法 :LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释 : 用于和split
,explode
等UDTF
一起使用,它能够将一列数据拆成多行数据在此基础上可以对拆分后的数据进行聚合;
5️⃣ 采用分桶技术
6️⃣ 采用分区技术
7️⃣ 合理设置Map
数
(1)通常情况下作业会通过input
的目录产生一个或者多个map
任务;
主要的决定因素有 :input
的文件总个数,input
的文件大小,集群设置的文件块大小;
(2)是不是map
数越多越好?
答案是否定的,如果一个任务有很多小文件(远远小于块大小128m
)则每个小文件也会被当做一个块用一个map
任务来完成,而一个map
任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费;而且同时可执行的map
数是受限的;
(3)是不是保证每个map
处理接近128m
的文件块就可以了?
答案也是不一定,比如有一个127m
的文件正常会用一个map
去完成但这个文件只有一个或者两个小字段却有几千万的记录,如果map
处理的逻辑比较复杂用一个map
任务去做肯定也比较耗时;
针对上面的问题2
和3
我们需要采取两种方式来解决 : 即减少map
数和增加map
数;
8️⃣ 小文件进行合并
在Map
执行前合并小文件减少Map
数 :CombineHiveInputFormat
具有对小文件进行合并的功能(系统默认的格式)HiveInputFormat
没有对小文件合并功能;
9️⃣ 合理设置Reduce
数
Reduce
个数并不是越多越好
(1)过多的启动和初始化Reduce
也会消耗时间和资源;
(2)另外有多少个Reduce
就会有多少个输出文件如果生成了很多个小文件同时这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置Reduce
个数的时候也需要考虑这两个原则 : 处理大数据量利用合适的Reduce
数使单个Reduce
任务处理数据量大小要合适;
🔟 常用参数
// 输出合并小文件
SET hive.merge.mapfiles = true
: 默认true
在map-only
任务结束时合并小文件;
SET hive.merge.mapredfiles = true
: 默认false
在map-reduce
任务结束时合并小文件;
SET hive.merge.size.per.task = 268435456
: 默认256M
;
SET hive.merge.smallfiles.avgsize = 16777216
: 当输出文件的平均大小小于该值时启动一个独立的map-reduce
任务进行文件merge
;
网友评论