1. 程式人生 > >資料倉庫(十四)--java--presto---hive的分頁查詢

資料倉庫(十四)--java--presto---hive的分頁查詢

我們在SpringMVC框架中使用那個presto查詢hive的資料做展示時,發現在table裡分頁是個不可避免的話題。

建議去掉count

但是尷尬的是 對於海量資料 count的效率是很低的,因為在不加條件的情況下基本上要掃描全表。

count操作效能比較收集
oracle裡Count一億條資料 大於10分鐘
mysql,3000萬行記錄,count(*)需要200s
hive+presto count 8499萬條記錄 需要30s

效率對比如圖:

查詢準確資料只用了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表格由於資料量大,所以要做分頁還是比較麻煩的,所以在程式設計時儘可能的避免的分頁場景。