我有下表,第一个(Range)包括值范围和其他列:
Range
row | From | To | Country .... -----|--------|---------|--------- 1 | 1200 | 1500 | 2 | 2200 | 2700 | 3 | 1700 | 1900 | 4 | 2100 | 2150 | ...
该From和To是bigint和是互斥的。该Range表包括180万条记录。附加表(Values)包含270万条记录,如下所示:
From
To
bigint
Values
row | Value | More columns.... --------|--------|---------------- 1 | 1777 | 2 | 2122 | 3 | 1832 | 4 | 1340 | ...
我想创建一个表,如下所示:
row | Value | From | To | More columns.... --------|--------|--------|-------|--- 1 | 1777 | 1700 | 1900 | 2 | 2122 | 2100 | 2150 | 3 | 1832 | 1700 | 1900 | 4 | 1340 | 1200 | 1500 | ...
我用于BETWEEN上述任务,但查询永无止境:
BETWEEN
VALUES.VALUE between RANGE.FROM and RANGE.TO
我需要在表分区或Impala中进行更改吗?
以下解决方案的主要思想是用等式联接替换theta联接(非等式联接),这将导致良好的分布+高效的局部联接算法。
范围(无穷大,无穷大)被分割为一部分n长度。 范围表中的每个范围都与其相交的部分相关联。
n
例如,给定n = 1000,范围[1652,3701]将与section关联[1000,2000),[2000,3000)并且[3000,4000)(并且将具有3条记录,每个section 1条)
[1652,3701]
[1000,2000)
[2000,3000)
[3000,4000)
1652 3701 | | ------------------- ------------------------------------------------------- | | | | | | 0 1000 2000 3000 4000 5000
以相同的方式,将值表中的值与包含该值的范围相关联,例如,2093将与range关联[2000,3000)。
2093
2个表之间的联接将在表示该节的值上进行,例如[1652,3701],2093并且将在该节上进行联接[2000,3000)
create table val_range (id int,from_val bigint,to_val bigint); insert into val_range values (1,1200,1500) ,(2,2200,2700) ,(3,1700,1900) ,(4,2100,2150) ; create table val (id int,val bigint); insert into val values (1,1777) ,(2,2122) ,(3,1832) ,(4,1340) ;
set n=1000; select v.id ,v.val ,r.from_val ,r.to_val from (select r.* ,floor(from_val/${hiveconf:n}) + pe.i as match_val from val_range r lateral view posexplode ( split ( space ( cast ( floor(to_val/${hiveconf:n}) - floor(from_val/${hiveconf:n}) as int ) ) ,' ' ) ) pe as i,x ) r join val v on floor(v.val/${hiveconf:n}) = r.match_val where v.val between r.from_val and r.to_val order by v.id ;
+------+-------+------------+----------+ | v.id | v.val | r.from_val | r.to_val | +------+-------+------------+----------+ | 1 | 1777 | 1700 | 1900 | | 2 | 2122 | 2100 | 2150 | | 3 | 1832 | 1700 | 1900 | | 4 | 1340 | 1200 | 1500 | +------+-------+------------+----------+