我们对8400万条hive数据使用presto进行查询,数据量大约11G,不是很大。
前端web界面上只有一个输入框,通过这个输入框同时查询三个字段是否有相等的数据
使用查询语句主要涉及三个字段为:
select chromosome,position,rs from chip where 1=1 and (chromosome='156531656' or position='156531656' or rs='156531656' ) limit 20;
发现查询时间花费较长,花费在35s左右。
优化,对表进行分区处理,生成新表
create table chip_pt(id BIGINT,position string,rs string,linenum string,filename string,createdate string) partitioned by (chromosome string);
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=100000;
set hive.exec.max.dynamic.partitions.pernode.Maximum=100000;
set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.created.files=100000;
set mapred.max.split.size=1024000000;
set mapred.min.split.size.per.node=1024000000;
set mapred.min.split.size.per.rack=1024000000;
set mapred.reduce.tasks=100;
set hive.map.aggr=true;
set hive.groupby.skewindata=true;
set hive.enforce.bucketing = true;
insert overwrite table chip_pt
partition(chromosome)
select row_number() over (order by position) as id,position,rs,linenum,filename,createdate,chromosome from chip;
尝试查询发现当 所选参数是 分区字段时,查询速度很快,能达到300ms级别。
但是,如果使用的非 分区字段内容时,查询的时间还是在 30s左右。
我们把三个字段分开来进行查询尝试。
发现只要带有准确的分区字段chromosome内容的查询 条件 耗时都为 ms级别。
select position from chip_pt where chromosome='8' and position='156531656'
单个非分区字段position或者rs的查询 耗时为15s左右。
select position from chip_pt where position='156531656'
使用explain分析查询sql如下:
explain select position from chip_pt where position='156531656'
发现单一的条件扫描了全表。
使用or语句时,会一次扫描多次遍历全表。
所以我们需要在交互逻辑上优化sql语句,把查询输入框由一个拆分成三个,然后根据输入框是否为空,使用and来拼接查询语句。尽量少用or语句。
因为非分区字段的查询时间达不到1s内的查询要求,所以我们想进一步优化,除了分区之外还有一个思路就是加索引。
使用语句
增加索引
create index chip_index_position on table chip_pt(position)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
with deferred rebuild;
create index chip_index_rs on table chip_pt(rs)
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'
with deferred rebuild;
alter index chip_index_position on chip_pt rebuild;
alter index chip_index_rs on chip_pt rebuild;
增加索引后在presto中原语句查询发现并没有显著增加查询效率,时间还是在15s左右。
select position from chip_pt where position='156531656'
以为索引 没生效。但是使用explain查看以及在索引表中查询 都能查询到索引。
使用语句查询索引表
select position from chip_index_position where position='156531656';
desc chip_index_position;
使用explain分析查询索引表语句。
explain select position from chip_index_position where position='156531656';
发现在查询索引表时也需要全表扫描索引表,花费的时间本来就有13s左右。
所以也就是说 针对少数据量,索引并不能把presto查询hive的效率提高到1s内,最极限就是达到 查询索引所花费的时间。
1、hive的sql语句在使用时尽量少用or语句。
2、即时针对hive我们有presto这样的实时交互引擎,但是它优化的程度还是有限的,瓶颈就在索引扫描花费的时间上,所以如果是针对小数据量,要求1s内返回的查询场景,尽量不要存在hive,存在mongodb,mysql,hbase等场景比较合适。