我想知道人们在拥有大量数据时如何应对大型的一对多联接,尤其是非股权联接。如果两个表A
和B
的键是足够重复的,则两个表之间的联接输出可以接近| A
|的大小。 * | B
|。大型公司的分析中必须经常提到这一点,所以我想知道有什么方法可以减少这些联接的计算时间。
但是,A
和B
很多时候是不同的表,在这种情况下,我认为不能使用LAG()
。
作为可能需要非等号和一对多联接的情况的简化示例,我有表A
和B
,每个表都有数字{{1} }列,日期字段id
和某些字段date_created
。对于表group
中的每一行,我想要A
的{{1}}列以及表id
中相应行的所有数据,其中A
是最大的值,例如B
> B.date_created
和A.date_created
。换句话说,我想要表B.date_created
的最新行相对于列A.group = B.group
中每一行的B
和date_created
字段。
在大多数出现这些非等额联接的情况下,group
和A
是同一表,而A
字段实际上对应于同一列。在这种情况下,我可以使用B
窗口函数:
date_created
我相信它比自我加入更为有效。但是,当要比较的列不同或属于不同的表时,这种方法是不可能的。
我使用以下代码为表LAG()
中的每一行计算表WITH id_tuples AS
(
SELECT A.id,
LAG(A.id, 1) OVER (PARTITION BY A.group ORDER BY A.date_created) AS lagged_id
FROM A
)
SELECT id_t.id,
A.*
FROM id_tuples id_t
INNER JOIN A ON A.id = id_t.lagged_id
的最新行。
B
这里的问题是分组变量A
和SELECT *
FROM
(
SELECT A.id,
B.*,
DENSE_RANK() OVER (PARTITION BY A.id ORDER BY B.date_created) AS date_rank
FROM A
INNER JOIN B ON B.group = A.group
AND B.date_created < A.date_created
)
WHERE date_rank = 1
只能具有几个不同的值。然后,该联接几乎变成了笛卡尔联接,并且子查询中输出结果的数量可能比A和B的行之和大许多数量级。这很浪费,因为外部查询会丢弃大部分的通过过滤A.group
获得结果。
是否存在更好的结构化查询结构,以减少这些连接的成本,或者在这些情况下完全避免使用它们?我在摘要中询问,但是我发现我的关系数据库和Spark集群(一旦我将数据移到那里)都没有足够的内存来处理这种联接。即使在较小的数据集上,此操作也需要大量时间才能运行。而且我不认为我的数据集相对于其他人正在做的事情特别大。
答案 0 :(得分:0)
您的第一个查询可以简单地写为:
SELECT A.id,
LAG(A.id, 1) OVER (PARTITION BY A.group ORDER BY A.date_created) AS lagged_id
FROM A;
不需要JOIN
。
对于第二个查询,一种方法是横向联接:
SELECT A.id, B.*,
FROM A LEFT JOIN LATERAL
(SELECT B.*
FROM B
WHERE B.group = A.group AND
B.date_created < A.date_created
ORDER BY B.date_created DESC
FETCH FIRST 1 ROW ONLY
) B;
这应该在B(GROUP, date_created)
上使用索引。