如何对 hsqldb 中的大表执行高效的 group by / sum 聚合?
Posted
技术标签:
【中文标题】如何对 hsqldb 中的大表执行高效的 group by / sum 聚合?【英文标题】:How to perform efficient group by / sum aggregation on large tables in hsqldb? 【发布时间】:2018-04-11 09:18:39 【问题描述】:在我的 HSQL 数据库中,我有一个大型(>10M 行)缓存表“Products”,其中每个 Product 都有一个“groupId”和“value”列。 groupId 列上还有一个索引。在另一个缓存表“组”(也很大,> 1M 行)中,我需要存储属于该组的所有产品的所有聚合值。所以基本上我的查询看起来像这样:
MERGE INTO Groups AS g USING (
SELECT groupId, SUM(value) AS aggrValue
FROM Products GROUP BY groupId
) AS sub
ON g.groupId = sub.groupId
WHEN MATCHED THEN UPDATE SET g.value = sub.aggrValue
但是,这不适用于大型表,因为正如 documentation 在“操作期间的临时内存使用”下所述,受更新影响的所有行都将在操作期间保存在内存中。我还尝试使用此查询首先将聚合值写入帮助表:
INSERT INTO HelperTable (groupId, value)
SELECT groupId, SUM(value)
FROM Products
GROUP BY groupId
但这也超出了可用内存。我已经尝试过限制
hsqldb.result_max_memory_rows
设置为 100_000。聚合值并将它们写入 Groups 表的首选解决方案是什么?我的主要要求是无论产品和组的数量如何,该操作都以恒定内存运行。
【问题讨论】:
你试过把它分成更小的批次吗?喜欢 10000 行/插入? 不,但那是我想尝试的。是否可以在较小的批次上进行分组(即前 10k 分组,合并到组中,然后为下一个 10k 分组 ...)where id between 1 and 9999
第一次,然后where id between 10000 and 19999
等等。写一个循环。
好吧,看起来很奇怪,数据库不能自己处理这个问题,但我会试试的。
它真的无法做出这个决定。有时原子性很重要,有时则不重要。
【参考方案1】:
按照设计,HSQLDB 完全在内存中执行某些操作,例如 GROUP BY。它还将事务历史存储在内存中,直到提交。
您可以根据groupId
列分块执行操作。您需要在每个块之后提交。
您可以将更新开发为增量更新。添加新产品时,这些产品的值的总和将添加到存储的总和中。或者当产品被移除时,从存储的总和中减去值的总和。
【讨论】:
如何在考虑性能的情况下开发增量更新?使用数据库触发器? 数据库触发器是最好的选择 不能给你足够的支持来跟上 hsqldb 的支持以上是关于如何对 hsqldb 中的大表执行高效的 group by / sum 聚合?的主要内容,如果未能解决你的问题,请参考以下文章