如何对 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 聚合?的主要内容,如果未能解决你的问题,请参考以下文章

从mysql中的大表中快速选择随机行

通过自定义分区器对雪花中的大表进行分区

如何优化mysql中的大表?

Innodb中mysql如何快速删除2T的大表

从 SQL Server 中的大表中删除大部分数据的策略

从mysql中的大表中快速选择随机行