为什么我的HSQLDB表看起来像磁盘上的空间太大?

时间:2013-04-04 17:17:12

标签: hsqldb

我有以下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表)的磁盘使用情况摘要:

  1. 10,000行= 2.0MB
  2. 100,000行= 16MB
  3. 1,000,000行= 128MB
  4. 现在原始计算:  (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 个答案:

答案 0 :(得分: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'