为啥我的 HSQLDB 表在磁盘上占用了太多空间?

Posted

技术标签:

【中文标题】为啥我的 HSQLDB 表在磁盘上占用了太多空间?【英文标题】:Why does my HSQLDB table take seemingly way too much space on the disk?为什么我的 HSQLDB 表在磁盘上占用了太多空间? 【发布时间】:2013-04-04 17:17:11 【问题描述】:

我有以下 HSQLDB 架构:

CREATE TABLE RUNSTATS
(
   ID      BINARY(16)   NOT NULL,
   ENTITY  BLOB(128K)     NOT NULL
   ,CHECK (PUBLIC.RUNSTATS.ID IS NOT NULL)
   ,CHECK (PUBLIC.RUNSTATS.ENTITY IS NOT NULL)
);

ALTER TABLE RUNSTATS
   ADD CONSTRAINT pk_runstats
   PRIMARY KEY (ID);

CREATE TABLE RUNSTATS__AVGLATENCYINDEX
(
   ID          BINARY(16),
   TIMESTAMP   BIGINT,
   FLOWID      VARCHAR(200),
   AVGLATENCY  DOUBLE
);

ALTER TABLE RUNSTATS__AVGLATENCYINDEX
   ADD CONSTRAINT pk_runstats__avglatencyindex
   PRIMARY KEY (ID, FLOWID);

CREATE INDEX IDX_RUNSTATS__AVGLATENCYINDEX_FLOWID
   ON RUNSTATS__AVGLATENCYINDEX (FLOWID ASC);

RUNSTATS 表在 x.lobs 文件中,而 RUNSTATS__AVGLATENCYINDEX - 在 x.data

我插入 RunStats 对象,每个对象在 RUNSTATS 表中产生 1 行,在 RUNSTATS__AVGLATENCYINDEX 中产生 100 行。我运行三个会话,插入 100、1000 和 10000 个 RunStats 对象。

另一个非常重要的细节 - 实际的 FLOWID 值都是 20 个英文字符长,尽管字段是 VARCHAR(200)

请在下面找到 x.data 文件(包含 RUNSTATS__AVGLATENCYINDEX 表)的磁盘使用情况摘要:

    10,000 行 = 2.0MB 100,000 行 = 16MB 1,000,000 行 = 128MB

现在原始计算: (sizeOf(ID) + sizeOf(FLOWID) + sizeOf(TIMESTAMP) + sizeOf(AVGLATENCY)) = 16 + 20 + 8 + 8 = 52

所以 1,000,000 行大约需要 52 * 1,000,000 = ~50MB

最佳尺寸比实际尺寸小一倍以上。

这是正常的数据库开销吗?我可以指示 hsqldb 引擎更有效地利用空间吗?

更多上下文:

仅添加实体(从不删除) 有一个明确定义的时期,即以固定速度添加实体。例如,每 10 秒一次,持续 3 天。之后 - 不再添加实体。

编辑

请在此处找到压缩脚本文件 - https://docs.google.com/file/d/0B2pbsdBJxJI3Z2dFTndMZnBMU2c/edit?usp=sharing

【问题讨论】:

【参考方案1】:

我在 RUNSTATS__AVGLATENCYINDEX 表中插入了 1,000,000 行,.data 文件的大小为 128MB。额外的大小是由于主键和表上的额外索引(32 字节)以及行、字符串和可空性信息的长度。 FLOWID 列使用 20 + 5 个字节。总共每行需要 32 + 12 + 4 个字节的额外空间,所以总共是 100 个字节。这被放大到 32 字节的倍数 (FILE SCALE),因此每行 128 字节。

检查您的 .script 文件。如果您有SET FILE SCALE 256 或更高版本,这可以解释额外的空间。每行的大小是这个 SCALE 值的倍数。

使用默认 SCALE 32 和给定的 FLOWID 大小,每行应使用 128 个字节。

您还可以对数据库执行 SHUTDOWN COMPACT 并在删除已删除的行后查看大小。

您已添加指向 .script 文件的链接。 SET TABLE ... 语句表示大表中有 751700 行。每行占用磁盘 128 个字节。

SET FILES SCALE 32
...
CREATE CACHED TABLE PUBLIC.RUNSTATS(ID BINARY(16) NOT NULL PRIMARY KEY,ENTITY BLOB(128K) NOT NULL)
CREATE CACHED TABLE PUBLIC.RUNSTATS__AVGLATENCYINDEX(ID BINARY(16),TIMESTAMP BIGINT,FLOWID VARCHAR(200),AVGLATENCY DOUBLE,PRIMARY KEY(ID,FLOWID))
CREATE INDEX IDX_RUNSTATS__AVGLATENCYINDEX_FLOWID ON PUBLIC.RUNSTATS__AVGLATENCYINDEX(FLOWID)
...
SET TABLE PUBLIC.RUNSTATS INDEX '4021 0 7517'
SET TABLE PUBLIC.RUNSTATS__AVGLATENCYINDEX INDEX '4039 79 0 0 751700'

【讨论】:

只添加的行,没有删除任何内容。但是我运行了 SHUTDOWN COMPACT - 没有效果,正如预期的那样。我可以在脚本文件中看到SET FILES SCALE 32 也许你还有其他的表,或者这些表更大。检查 .script 文件中的 SET TABLE xxx INDEX nn nn nn 语句。最后一个数字是表格的行数。 你是对的,愚蠢的我。还有一张桌子。我将从架构中删除它,重新运行整个测试,然后更新问题。

以上是关于为啥我的 HSQLDB 表在磁盘上占用了太多空间?的主要内容,如果未能解决你的问题,请参考以下文章

系统存储在 macOS Mojave 中占用了太多空间

为什么我的Android应用程序类占用了太多空间

JFrame 中的 JTextField 在实际文本字段之外占用了太多空间

确定哪个表在 MySQL 中占用最多的磁盘空间

Redshift 表在生产集群中占用的磁盘空间呈指数增长

“文件夹”-“属性”为啥查看文件大小和占用空间数据是变化的?