如果您有一个包含大型 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 年 9 月 19 日)。
更新:SQLite 版本 3.19.0(2017 年 5 月 22 日)的新测量结果表明,对于 10KB blob 的读写,SQLite 比直接磁盘 I/O 快约 35%。
下面的矩阵显示了读取存储在单独文件中的 BLOB 所需的时间除以读取完全存储在数据库中的 BLOB 所需的时间。因此,对于大于 1.0 的数字,将 BLOB 直接存储在数据库中更快。对于小于 1.0 的数字,将 BLOB 存储在单独的文件中更快。
在每种情况下,都会调整页面缓存大小,以使缓存内存量保持在约 2MB。例如,对于 1024 字节的页面,使用 2000 页缓存,对于 65536 字节的页面,使用 31 页缓存。BLOB 值以随机顺序读取。
数据库页面大小 | BLOB 大小 | ||||||
---|---|---|---|---|---|---|---|
10k | 20k | 50k | 100k | 200k | 500k | 1m | |
1024 | 1.535 | 1.020 | 0.608 | 0.456 | 0.330 | 0.247 | 0.233 |
2048 | 2.004 | 1.437 | 0.870 | 0.636 | 0.483 | 0.372 | 0.340 |
4096 | 2.261 | 1.886 | 1.173 | 0.890 | 0.701 | 0.526 | 0.487 |
8192 | 2.240 | 1.866 | 1.334 | 1.035 | 0.830 | 0.625 | 0.720 |
16384 | 2.439 | 1.757 | 1.292 | 1.023 | 0.829 | 0.820 | 0.598 |
32768 | 1.878 | 1.843 | 1.296 | 0.981 | 0.976 | 0.675 | 0.613 |
65536 | 1.256 | 1.255 | 1.339 | 0.983 | 0.769 | 0.687 | 0.609 |
我们从上面的矩阵中推导出以下经验规则
对于大型 BLOB I/O,8192 或 16384 的数据库页面大小可提供最佳性能。
对于小于 100KB 的 BLOB,当 BLOB 直接存储在数据库文件中时,读取速度更快。对于大于 100KB 的 BLOB,从单独的文件中读取速度更快。
当然,您的实际情况可能会因硬件、文件系统和操作系统而异。在确定特定设计之前,请在目标硬件上仔细检查这些数据。