HSQLDB:为现有数据库启用 LOB 压缩

HSQLDB: enable LOB compression for existing database

我正在使用嵌入式 HSQLDB 2.3.2 实例将 XML 文档作为 LOB 存储在一个应用程序中一段时间​​,该应用程序与文档应该结束的任何地方都有间歇性连接。

为了限制 HSQBDL 的 .lobs 文件大小增长,我通过 jdbc 连接 URL 启用了 LOB 压缩,如 documentation 中所述(使用 hsqldb.lob_compressed=true) ,但据我最近发现,这个 URL 参数没有任何效果。

如果我正确理解 HSQLDB JDBC URL 解析代码,org.hsqldb.persist.Logger#setVariables() 应该在某些时候检查 HsqlDatabaseProperties.hsqldb_lob_file_compressed 以设置 propCompressLobs,就像它所做的那样对于 LOB crypto & cryptLobs,但从来没有这样做。

在 URL 中使用此类参数创建的数据库中的 database.script 文件没有提及 LOB 压缩,尽管有 URL 参数,并且不压缩 LOB。

我试过在打开数据库后立即发出一个 "SET FILES LOB COMPRESSED TRUE" 语句,这对一个全新的数据库来说是正确的(lobs 被压缩,database.script 提到了 LOB 压缩)。

当我使用现有数据库之一尝试此操作时,由于现有 LOB(错误消息是 "data file in use"),我收到错误消息。我理解这背后的原因,因为压缩所有 LOB 可能需要一段时间,并且可能是一个很长的 运行 操作,如果中断可能会使数据库处于不良状态。

我想我可以解决这个限制,因为有时 XML 文档会被删除(在它们最终被发送之后),所以理论上 DB 在某个时候没有 LOB。

不幸的是,这个错误也会发生在空数据库上,因为删除的 LOB 中有未使用的 LOB 条目,我假设将其保留在那里以回收 .lobs 文件 space。似乎负责允许 LOB 压缩模式更改的 org.hsqldb.persist.Logger#setLobFileCompressed() 方法只检查 SYSTEM_LOBS.LOB_IDS 中的条目数,无论它们当前是否正在使用。

据我所知,没有办法清除已删除的 LOB 条目(例如减少 .lobs 文件大小)所以基本上即使当前存储在 LOB 中的所有 XML 文档都已发送并从数据库中清除,这不是启用压缩的好时机,因为删除的 LOB 会留下足迹,从而阻止启用压缩。

没有留下任何文档时关闭数据库,销毁它,创建一个新的数据库,然后手动发出 lob 压缩语句,我看不出有任何方法可以为具有现有文档的应用程序启用 LOB 压缩数据库。

我不是特别喜欢那个看起来很老套的选项。

我还没有尝试过 2.3.3,但是从我看到的 sources 来看,那个版本看起来并没有更好。

是否有任何其他方法可以可靠地启用现有 HSQLDB 数据库的 LOB 压缩?甚至 "empty" 个 ?

URL上的压缩设置只有在创建数据库时才有效。 SQL 设置可以在没有 lob 历史记录的空数据库上执行。

压缩功能是在支持非压缩 lob 数据的 2.0 版本之后很长时间添加的。无法更改现有数据库的设置。

如果数据库中没有 lob,您应该可以执行 CHECKPOINT,然后使用 SQL 设置。如果这不起作用,还有下一个选项。

如果数据库中没有 lob(但可以有其他数据),您可以关闭数据库,然后编辑 .script 文件并删除 SYSTEM_LOBS 的 INSERT INTO ... 条目并添加默认值出现在新数据库中的条目 INSERT INTO BLOCKS VALUES(0,2147483647,0)。如果这样做,您也应该删除 .lobs 文件。

您可以使用 SQL 到 select 形成 SYSTEM_LOBS 表来检查它们的内容,但不能修改它们。

我找到了一种可靠的方法,只需要 SQL,无论数据库是新数据库还是已经看到一些 activity.

的现有数据库
  • 确保有 0 个现有 LOB 使用 select count(*) from SYSTEM_LOBS.LOB_IDS
  • 在具有 LOB 的任何 table 中插入一行,以便将 LobManager usageChanged 设置为 true。
  • 提交。
  • 删除您刚刚创建的行。
  • 再次提交。
  • 执行 CHECKPOINT 以便清除所有 lob 元数据。由于最近添加了一个 LOB,检查点实际上将 运行 LobManager.deleteUnusedLobs() 并清理未使用的 lob 条目。
  • 使用 SET FILES LOB COMPRESSED TRUE 启用压缩。现在可以使用了,因为 SYSTEM_LOBS.LOB_IDS table.
  • 中不再有任何内容

如果您想要可靠地trim HSQLDB .lobs 文件,该文件由于压缩未激活而变大:

  • 插入带有 LOB 的另一行,以便 HSQLDB 可以计算 lob space 用法(LobManager.getLobUseLimit 在检查点期间没有 LOB 时不起作用)
  • 提交
  • 再次执行 CHECKPOINT 以便 lob 文件 trim 正常使用。
  • 删除您在检查点之前创建的行。
  • 提交