为啥在嵌入式 HSQLDB 上运行更新查询会消耗大量内存?
Posted
技术标签:
【中文标题】为啥在嵌入式 HSQLDB 上运行更新查询会消耗大量内存?【英文标题】:Why does running an update query on an embedded HSQLDB consume a lot of memory?为什么在嵌入式 HSQLDB 上运行更新查询会消耗大量内存? 【发布时间】:2018-06-05 08:50:20 【问题描述】:我正在使用 HSQLDB 2.4.1(嵌入缓存表)。我有一个大型数据库(大约 2100 万行。数据库大小为 5GB) 我正在尝试运行以下查询:
UPDATE TABLE_NAME SET COLUMN1=0
我尝试更改和使用这些属性,但最终此更新语句消耗了大量内存,就好像它将整个数据库复制到内存中一样。
properties.setProperty("hsqldb.large_data" , "true");
properties.setProperty("hsqldb.log_data" , "false");
properties.setProperty("hsqldb.default_table_type" , "cached");
properties.setProperty("hsqldb.result_max_memory_rows" , "50000");
properties.setProperty("hsqldb.tx" , "mvcc");
properties.setProperty("sql.enforce_tdc_update" , "false");
properties.setProperty("shutdown" , "true");
properties.setProperty("runtime.gc_interval" , "100000");
当我在 DBeaver 中执行此查询时,我注意到内存消耗显着增加并不断增加,直到达到 4GB 的 maxmem,此时应用程序因内存不足错误而崩溃。
PS:在相同的嵌入式 Derby 数据库上运行此精确查询大约需要 5 分钟,但最终返回并且 DBeaver 中的内存使用量保持在约 400mb 左右。
【问题讨论】:
【参考方案1】:所有更新的行都加载到内存中直到提交。您可以根据主键和 LIMIT 子句分块更新。例如:
UPDATE TABLE_NAME SET COLUMN1= 0 WHERE COLUMN1 != 0 AND (PK_ID > 1000000 AND PK_ID < 2000000) LIMIT 1000000
上面的语句显示了两种不同的技术来限制行。首先,通过使用索引列来限制;其次,在更新了许多行后使用 LIMIT 停止更新。
http://hsqldb.org/doc/2.0/guide/dataaccess-chapt.html#dac_update_statement
【讨论】:
鉴于 hsqldb.result_max_memory_rows=50000,这不应该意味着只能将 50000 行加载到内存中吗?还是在使用 UPDATE 查询时不尊重此属性? 没有。该设置仅适用于 SELECT 语句。以上是关于为啥在嵌入式 HSQLDB 上运行更新查询会消耗大量内存?的主要内容,如果未能解决你的问题,请参考以下文章