组织具有大量数据行的表以优化访问时间

Organizing tables with data-heavy rows to optimize access times

我现在正在使用大约 70 GB 的 sqlite3 数据库。这个数据库有三个 table:一个有大约 3000 万行,另外两个分别有 ~150 和 ~3 亿,每个 table 运行 来自 6-11 列。

行数最少的 table 占用了 space 的大部分内容,因为它包含一个压缩的 BLOB 原始数据列,通常在 运行 之间每行 1 和 6 KB;数据库中的所有其他列都是数字,压缩数据是 immutable 所以修改效率低下不是问题。

我注意到在 table:

的数字列上创建索引
[15:52:36] Query finished in 723.253 second(s).

花费的时间是在 table 上创建可比索引的几倍,行数是其五倍:

[15:56:24] Query finished in 182.009 second(s).
[16:06:40] Query finished in 201.977 second(s).

BLOB 数据存储在单独的 table 中以便使用 JOIN 访问是否更好?每行的额外宽度最有可能导致此 table.

的扫描速度较慢

我目前的怀疑是:

  1. 这主要是由于从磁盘读取数据的方式,使得跳过中等数量的数据变得不切实际,并且操作系统从磁盘读取的每个扇区的可用数据比率非常低,并且
  2. 因此,作为关系数据库的新手,我不知道如何避免将较大的、可变宽度的数据放入与可能需要扫描的其他数据相同的 table 中,这可能是标准做法指数

但如果有人在该领域拥有更多知识,我将不胜感激。

SQLite file format中,一行中的所有列值简单地附加在一起,并存储为行值。如果该行太大而无法放入一个数据库页面,则剩余数据将存储在溢出页面的链表中。

当 SQLite 读取一行时,它只读取所需的部分,但必须从行的开头开始。

因此,当您有一个 blob(或一个大文本值)时,您应该将它移到列列表的末尾,这样就可以读取其他列的值而不必通过溢出页面列表:

CREATE TABLE t (
    id INTEGER PRIMARY KEY,
    a INTEGER,
    [...],
    i REAL,
    data BLOB NOT NULL,
);

对于单个 table,blob 值的第一个字节仍存储在 table 的数据库页面内,这减少了一页中可以存储的行数。

如果经常访问其他列,则将 blob 移动到单独的 table 可能有意义(不需要单独的文件)。这允许数据库在读取页面时一次浏览更多行,但会增加查找 blob 值所需的工作量。