文章目录
1.行存储和列存储
- 列存储:每个文件存储一个列,多个文件存储多个列,多个文件合成一张二维表
优点:
- 针对列的增删改查都很容易
- 列单独存储,对于每个列都可以进行单独排序,性能更好
- 列单独存储,可以针对每个列的数据类型设置针对性的压缩算法
- 可以指定列加载到内存中,更加节省内存
缺点:对于整行的操作性能很低,同时对事务的支持性不行
- 行存储:数据行存储,一个文件表达二维表
优点:
- 概念简单容易理解,日常生活中用到的都是行存储,例如CSV和Txt文件
- 针对行操作更快捷
- 事务性操作比较好
缺点:
- 针对列的操作性比较低,无论操作哪个列都要取出一整行的数据
- 不能针对列的数据类型设置压缩算法,压缩率不高(相对于列存储)
- 只能针对某一列进行排序,不能针对每个列进行排序
- 扩展列、删除列不方便
2.Hive分区
- 静态分区
insert into … partition(year=‘2020’, month=‘09’) - 动态分区
insert into ...... partition(year, month)
开启动态分区,同时要求非严格模式
set hive.exec.dynamic.partition=true; 是开启动态分区
set hive.exec.dynamic.partition.mode=nonstrict;
这个属性默认值是strict,就是要求分区字段必须有一个是静态的分区值,当前设置为nonstrict,那么可以全部动态分区
- 混合分区
这种方式要求静态在前:
insert into ......partition(year='2020', month)
- 相关设置参数
3.Hive分桶优化
- 概念:分桶和分区不同,分区是粗粒度的划分数据,并且是大范围的,分区划分的是文件夹,分桶划分的是文件
分区机制:分区就是通过文件夹的方式大范围切分表数据
分桶机制:分桶就是通过文件的方式在细粒度上切分表数据
- 什么时候用分桶?
1.查询性能优化(在有join的场景下)
如果分区数量过多,会对文件系统造成负载压力。
分桶是hash散列,如果分桶key相同,一定在一个文件内。当进行JOIN的时候,分桶就可以帮助完成文件与文件的对应。提升JOIN的性能
2.数据采样
我们用的都是大数据系,特点是数据量够大。
大量的数据如果做验证,比较消耗性能。
如果能够抽取一部分数据做验证,分桶就比较适合做数据采样用。
- 分桶表的数据写入
分桶表,不能够用load data的形式加载,也就是说只能够INSERT
来执行数据插入。
也就是,分桶表不能够直接用sqoop导入数据
sqoop导入方案:创建一个不带分桶的临时表,用sqoop将数据导入临时表。
再执行:INSERT INTO 正式表 SELECT * FROM 临时表;
4.MapJoin优化
- MapJoin优化:将Join发生在Map端,而不再Reduce端
- 如果在map端Join,每一个map都要有对应的数据存在内存中,也就是:
- 主表数据分散在各个map中
- 被关联的表,肯定要全量的存在各个map的内存中
- 场景限制
一般用于大表Join小表的场景 - 参数
# 开启自动执行MapJoin(达到条件,会自动走Map的Join而不是Reduce的Join)
set hive.auto.convert.join=true;
# 使用MapJoin的阈值设置,默认是20MB
set hive.auto.convert.join.noconditionaltask.size=512000000
/* 这个设置表示,如果N张表执行Join,N - 1张表的大小小于这个阈值,即可走MapJoin */
- 显式的告知Hive走MapJoin
在查询中加入:`/*+mapjoin(表)*/`
示例:
select /*+mapjoin(A)*/ f.a,f.b from A t join B f on ( f.a=t.a and f.ftime=20110802) ;
5.Bucket-MapJoin(桶表的MapJoin)
- 桶MapJoin
在大表和大表的场景下,无法使用MapJoin(因为大表指的就是超过了MapJoin允许的大小阈值) - 解决:使用Bucket-MapJoin来进行优化
- Bucket-MapJoin优化过程:表整体无法在Map中hold住,可以将表的分桶在Map中hold住,相同于两个表的分桶和分桶之间,做局部的
局部的MapJoin
- 限制条件
- 必须有分桶
- bucket数是另一个表bucket数的整数倍
也就是可以一个桶对一个桶,或者一个桶对两个桶等。
但不能出现一个桶对1.3个桶 - 分桶列也是JOIN列
- 参数
# 开启bucket mapjoin的优化
set hive.optimize.bucketmapjoin = true;
6.SMB Join(Sorted Merge Bucket Join)优化
MapJoin优化了整表的Join流程(整表在Map内存中Join)
BucketMapJoin优化了表的局部Join(桶文件和桶文件之间在Map端的内存中Join)
SMB Join优化的是,在Shuffle过程中的性能提升(将每个桶中的数据按某一列排序)
由MapReduce的执行流程可以知道:Map和Reduce之间有Shuffle,Shuffle是需要消耗一定的时间
如果提供的数据就死已排好序的,Shuffle就可以被加速
SMB的核心:在BucketMapJoin的基础上,对桶文件进行排序
通俗一点来说就是:分桶+排序
参数
# 开启排序
set hive.enforce.sorting = true;
# 开启SMB优化的自动尝试
set hive.optimize.bucketmapjoin.sortedmerge = true;
总结:
参数总结:
# 开启自动执行MapJoin(达到条件,会自动走Map的Join而不是Reduce的Join)
set hive.auto.convert.join=true;
# 使用MapJoin的阈值设置,默认是20MB
set hive.auto.convert.join.noconditionaltask.size=512000000
# 开启bucket mapjoin的优化
set hive.optimize.bucketmapjoin = true;
# 开启排序
set hive.enforce.sorting = true;
# 开启SMB优化的自动尝试
set hive.optimize.bucketmapjoin.sortedmerge = true;
7.Hive索引
-
索引:本质上就是将数据查询的
检索次数
和需要加载的数据量
进行优化的一种手段
大白话:加速查询的过程 -
优点:就是查的超快
-
缺点:增、删、改就是性能拖累
对于数据库表而言,支队频繁使用过滤条件或者关联条件的列加索引最好,不要全都加 -
从时间复杂度和空间复杂度去分析索引:
索引是以时间+空间换时间的操作
- 前面的时间指的是,插入、更新、删除等操作变慢
- 后面的时间指的是,查询的速度变快
- 空间指的是:额外的存储来记录索引信息
- Hive索引类型
- Hive原始索引(3.0废弃)
不会自动跟随数据更新而更新,每次更细数据都需要 - Row Group Index(行组索引)
- Bloom Filter Index(布隆过滤器索引)
行组索引和布隆过滤器索引,都需要使用ORC
行组索引
概念:针对某个列,行组索引是在ORC文件的每一个分块上,构建分块中针对某个列的最大值和最小值记录,通过这个记录,来确保索引数据,查询数据的时候可以pass掉大部分数据。
条件:
- Hive的表存储是
ORC
- 创建表的时候指定
TABLEPROPERTIES
中有:orc.create.index = true
- 数据插入的时候是有序插入
- 主要应用
数值类型
的列,用于:> >= < <= !=
的判断
如何使用:
创建表:
CREATE TABLE xxx stored AS ORC
TABLEPROPERTIES(
-- 开启压缩
'orc.compress' = 'SNAPPY',
-- 开启行组索引
'orc.create.index = true'
);
插入数据:
INSERT INTO TABLE xxx SELECT ......
DISTRIBUTE BY id SORT BY id;
查询数据:
set hive.optimize.index.filter=true; -- 自动使用索引优化
SELECT * FROM xxx WHERE id < 100;
布隆过滤器
对ORC中每个分块的数据,做分块索引
确保=
的查询是很快的。
如果确定了分块,那么`=`判断很快。
如果不确定分块,需要挨个判断。
最好和行组索引一起使用,行组可以加速对分块的判断。
布隆索引可以加速对分块内数据的`=`判断
条件:
- 必须是ORC存储
- 创建表的时候指定
TABLEPROPERTIES
中有:orc.bloom.filter.columns = '字段列表逗号分隔'
- 只用于
=
判断
如何使用:布隆过滤器索引可以和行组过滤器索引一起使用,效果更好。
建表:
CREATE TABLE xxx stored AS ORC
TABLEPROPERTIES(
-- 开启压缩
'orc.compress' = 'SNAPPY',
-- 开启行组索引
'orc.create.index = true',
-- 开启布隆过滤器
"orc.bloom.filter.columns" = "id,price"
);
插入数据:
无要求(针对布隆过滤器)
如果使用了行组,请有序写入
查询数据:
set hive.optimize.index.filter=true; -- 自动使用索引优化
SELECT * FROM xxx WHERE id = 1000;
索引使用的限制:不要乱加索引,有消耗
使用环境:
- 作为关联条件的可以用索引
- 经常被WHERE的可以选择行组过滤索引
- 经常被
=
的,可以选择布隆过滤器