presto java 分页_数据仓库(十四)--java--presto---hive的分页查询

本文探讨了在使用Presto查询Hive数据时遇到的分页问题,指出COUNT操作在海量数据下效率低下,并提出了去掉COUNT、预设数据量以及通过ID进行分页的建议。在Hive中,由于不支持LIMIT offset, limit,文章推荐使用BETWEEN结合自增ID进行分页,并介绍了如何通过row_number()函数生成自增列。最后,提醒在设计时尽量避免大量数据的分页场景。" 125542354,13029872,IDEA自动化部署利器:阿里CloudToolkit,"['jenkins', 'spring boot', '自动化', '插件', 'Docker']
摘要由CSDN通过智能技术生成

我们在SpringMVC框架中使用那个presto查询hive的数据做展示时,发现在table里分页是个不可避免的话题。

建议去掉count

但是尴尬的是 对于海量数据 count的效率是很低的,因为在不加条件的情况下基本上要扫描全表。

count操作性能比较收集

oracle里Count一亿条数据 大于10分钟

mysql,3000万行记录,count(*)需要200s

hive+presto count 8499万条记录 需要30s

效率对比如图:

Foea-ZJ2weg9DcXQ4JxQNoSYWebN

查询准确数据只用了214毫秒,查询数量count却花了39秒的时间,如果我们要先获取准确的数量的话就做不到迅速响应的查询。

所以我们建议在海量数据列表显示时去掉count,默认给比较大的数值,包含所有的数据量。

如果需要准确count的场景,建议增加下拉框选择准确count的模式下再去查询count并说明该模式需要更长的查询时间。

如何分页

在使用hive的sql语句查询时,很悲伤的发现hive的sql没有limit 5,20 的用法,只有limit 20,只能限制条数,不支持直接跳过多少条数据。

还好hive支持使用where id between 10 to 20 或者 时间。

例如

select * from table t1 where t1.DATE_COLUMN between cast(from_unixtime(unix_timestamp(),'yyyy-MM-01 00:00:00') as timestamp) and cast(from_unixtime(unix_timestamp()) as timestamp) ;

limit 与between的区别在于

limit是根据查询出的结果里进行跳过和条数限制。

between则作为查询条件来使用。如果针对全量表 between是比较好进行分页的。 但是对于有查询条件的时候,between就比较复杂了,因为查询条件查出来的数据 列的值的范围是多少 我们并不知道。

所以 需要另外的一种 分页逻辑,数值类型int类型的自增id。

只要id的排序顺序一定,无论我们的查询条件是什么,查询出来的数据都是有序的,而且id有范围。

使用命令如下:

#获取第一页数据:

select * from table where type=2 order by id asc limit 10;

#获取第二页数据:

#需要获取第一页10条中最大的id为preId,作为下一页的条件。

int preId=select max(id) from table where type=2 order by id asc limit 10;

select * from table where type=2 and id >preId order by id asc limit 10;

#获取第三页数据:

#需要获取2页20条中最大的id为preId,作为下一页的条件。

int preId=select max(id) from table where type=2 order by id asc limit 20;

select * from table where type=2 and id >preId order by id asc limit 10;

总结

可以看到第一个limit的数值是跳过的条数,第二个limit是每页的条数。

自增列id生成

在我们设计的hive分页逻辑中,很重要的一个辅助字段就是唯一不重复的自增id。

这个在把数据写入分布式集群时如何生成不重复的自增数值id目前还没有找到很好的方法。

但是 通过hive的row_number()方法可以很好的在新表中统一生成自增列。

使用命令

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;

注意id必须使用int类型才能很好的进行排序分页。

当然这种方式针对海量数据来说还是有点麻烦,也就是每次有更新数据都得重新生成一次带有自增列的新表。

除此之外 自己在写入hive时维护自增列也是一种思路,不过比较麻烦而且容易有重复的自增id。

总结

hive表格由于数据量大,所以要做分页还是比较麻烦的,所以在程序设计时尽可能的避免的分页场景。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值