SQLite 中的内部 BLOB 与外部 BLOB

如果您有一个包含大型 BLOB 的数据库,当您将完整的 BLOB 内容直接存储在数据库中时,读取性能会更好吗?还是将每个 BLOB 存储在一个单独的文件中并仅将相应的文件名存储在数据库中会更快?

为了尝试回答这个问题,我们在 Linux 工作站(大约 2011 年的 Ubuntu,在快速 SATA 磁盘上使用 Ext4 文件系统)上运行了 49 个具有各种 BLOB 大小和 SQLite 页面大小的测试用例。对于每个测试用例,都会创建一个包含 100MB BLOB 内容的数据库。BLOB 的大小从 10KB 到 1MB 不等。BLOB 的数量有所不同,以便将总 BLOB 内容保持在大约 100MB。(因此,1MB 大小有 100 个 BLOB,10K 大小有 10000 个 BLOB,等等。)使用了 SQLite版本 3.7.8 (2011-09-19)。

更新:SQLite 版本 3.19.0 (2017-05-22) 的新测量表明, 对于 10KB blob 的读取和写入,SQLite 比直接磁盘 I/O 快约 35% 。

下面的矩阵显示了读取存储在单独文件中的 BLOB 所需的时间除以读取完全存储在数据库中的 BLOB 所需的时间。因此,对于大于 1.0 的数字,将 BLOB 直接存储在数据库中会更快。对于小于 1.0 的数字,将 BLOB 存储在单独的文件中会更快。

在每种情况下,页面缓存大小都进行了调整,以将缓存内存量保持在大约 2MB。例如,2000 页面缓存用于 1024 字节页面,31 页面缓存用于 65536 字节页面。BLOB 值以随机顺序读取。

数据库页面大小BLOB 大小
10k20k50k100k200k500k1m
10241.5351.0200.6080.4560.3300.2470.233
20482.0041.4370.8700.6360.4830.3720.340
40962.2611.8861.1730.8900.7010.5260.487
81922.2401.8661.3341.0350.8300.6250.720
163842.4391.7571.2921.0230.8290.8200.598
327681.8781.8431.2960.9810.9760.6750.613
655361.2561.2551.3390.9830.7690.6870.609

我们从上面的矩阵中推导出以下经验法则:

当然,您的里程可能因硬件、文件系统和操作系统而异。在进行特定设计之前,请仔细检查目标硬件上的这些数字。