网上关于Hive调优的视频、博客等相当多,但是也很杂。本文总结记录Hive企业使用时常见的优化策略。
为什么有的sql执行mapreduce,而有的却不?比如执行select * 的时候不会跑MR,这其实就是优化,属于FetchTask。
hive.fetch.task.conversion
minimal
Some select queries can be converted to single FETCH task minimizing latency.
Currently the query should be single sourced not having any subquery and should not have
any aggregations or distincts (which incurs RS), lateral views and joins.
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more : SELECT, FILTER, LIMIT only (TABLESAMPLE, virtual columns)
该配置的描述:某些选择查询可以转换为单个FETCH任务,从而最大程度地减少延迟。
默认参数:minimal,表示对select *、分区字段过滤、limit语法,不使用MR。改为more的话,会支持更多的FetchTask。
子查询:将子查询的结构赋予一张新的表;用于分表。
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
# 中间是对表的设置,如:
[
[ROW FORMAT row_format]
[STORED AS file_format]
| STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later)
]
[LOCATION hdfs_path]
#
[AS select_statement];
举例:
create EXTERNAL table dept_ext( # 加EXTERBAL
deptno int,
dname string,
loc string
)
row format delimited fields terminated by '\t'
LOCATION '/user/hive/warehouse/db_emp.db/dept'; # LOCATION指定位置
CREATE EXTERNAL TABLE [IF NOT EXISTS] [db_name.]table_name
[(col_name data_type [COMMENT col_comment], ...)]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[ROW FORMAT row_format]
举例:
create table emp_part(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
PARTITIONED BY (event_month string,hour string)
row format delimited fields terminated by '\t';
load data local inpath '/opt/datas/emp.txt' into table emp_part PARTITION(date='20191212',hour='12');
load data local inpath '/opt/datas/emp.txt' into table emp_part PARTITION(date='20191212',hour='13');
分区表建立完成后,用dfs -put 方法加载数据文件之后,会发现查不到数据。原因在于存储元数据的数据库里,没有元数据信息。有两种修复方式如下,企业中常用第二种。
第一种方式:msck repair table table_name;
第二种方式:alter table table_nameadd partition(分区条件);
举例如下:
dfs -mkdir -p /user/hive/warehouse/dept_part/day=20191212;
dfs -put /opt/datas/dept.txt /user/hive/warehouse/dept_part/day=20191212;
第一种方式:
hive(default)>msck repair table dept_part;
第二种方式
alter table dept_part add partition(day='20191212');
外部表和分区表使用方式:结合使用,多级分区
对于这一块,可以参照本人另一篇文章Hive数据格式
定义:Join发生在Reduce Task阶段
使用场景:大表对大表,每个表的数据都是从文件中读取的。
定义:Join发生在Map Task阶段
使用场景:小表对大表,大表的数据从文件中读取,小表的数据放在每个节点的内存中。由DistributionCache类实现。
SMB Join的流程:先对两个大表按某个字段进行排序,对于上图而言,自然应该是customer.id和order.cid;排序完之后将表分成若干个“桶”,如下示例的3 bucket,每个对应的bucket之间进行Join。
customer
3 bucket
1st
1001 - 1101
2nd
1201 - 1401
3rd
1501 - 1901
order
1st
1001 - 1101
2nd
1201 - 1401
3rd
1501 - 1901
hive.auto.convert.join=true;
官网Explain描述
EXPLAIN [EXTENDED|CBO|AST|DEPENDENCY|AUTHORIZATION|LOCKS|VECTORIZATION|ANALYZE] query
针对有些互相没有依赖关系的独立的job,可以选择并发的执行job。
如一个语句里有多个job
job1:a join b,结果:ab
job2:c join d,结果:cd
job3:ab join cd
job1和job2之间没有依赖关系,可以并行执行。
hive.exec.parallel
hive.exec.parallel.thread.number
mapreduce.job.jvm.numtasks
min(max_split_size,max(min_split_size,block_size))
。其中,min_split_size默认值0(最小分片大小);
max取的时候取的是block_size,block_size默认是128;
max_split_size默认值256(最大分片大小);
这个公式决定了map的个数。
一般在实际的生产环境中HDFS一旦format格式化之后,block_size大小不会去修改的。
所以不能直接去修改HDFS的block_size,我们通过修改max_split_size和min_split_size来影响map的个数
mapreduce.job.reduces
mapreduce.map.speculative
mapreduce.reduce.speculative
hive.mapred.reduce.tasks.speculative.execution(这个也要设为false,曾经因为没有改,推测执行还保持存在)
公司的日志源表:company_log_src
假设有三个业务,对应三个表。表类型:外部表(技术部、销售部、产品部都要用),分区表(month,day)
table1:company_log_ip 与ip相关
/month=2019-12/day=12(company_log_ip目录下可以看到二级分区)
table2:company_log_page 与用户访问的网页有关
table3:company_log_refer 与用户怎么过来的有关
关于前端数据入库的方式
* 对于src表
load data ....
* 对应company_log_xx表
load data path '' into table company_log_ip partition(month='2019-12',day='12') ;
分区目录要手动创建,对于month每月创建可以接受,但是每天都要创建day分区,会很麻烦,所以要设置动态分区。
概念:在Strict Mode下,对分区表查询时,在where子句中没有加分区过滤的话,会报错。具体细节如下图。
生产环境下建议开启Strict Mode,因为它会检查我们写的SQL,如果出问题,可以赶紧修改。
备注
设置是:set hive.mapred.mode=strict;
查看是:set hive.mapred.mode;
业务场景:处理小数据集的时候,速度会更快一些
配置:hive.exec.mode.local.auto
本地模式的限制:数据的输入大小不能超过128MB
本地模式的限制:map数不能超过4个
本地模式的限制:reduce的个数不能超过1个
正在整理中