【发布时间】:2013-03-24 14:37:39
【问题描述】:
原问题
背景
众所周知,SQLite needs to be fine tuned 可以实现大约 50k 插入/秒的插入速度。这里有很多关于插入速度慢的问题以及大量的建议和基准。
还有claims that SQLite can handle large amounts of data,报告 50+ GB 并没有导致正确设置出现任何问题。
我已按照此处和其他地方的建议来实现这些速度,我对 35k-45k 插入/秒感到满意。我遇到的问题是,所有基准测试都只展示了 插入速度似乎与表格大小成反比。
问题
我的用例需要在链接表中存储 500m 到 1b 个元组 ([x_id, y_id, z_id]) 几年(1m 行/天)。这些值都是介于 1 和 2,000,000 之间的整数 ID。 z_id 上有一个索引。
前 10m 行的性能非常好,大约 35k 插入/秒,但是当表有大约 20m 行时,性能开始受到影响。我现在看到大约 100 次插入/秒。
桌子的大小不是特别大。 20m 行,磁盘大小约为 500MB。
该项目是用 Perl 编写的。
问题
这是 SQLite 中大型表的现实吗?还是有什么秘诀可以保持超过 10m 行的表的高插入率?
我希望尽可能避免的已知解决方法
- 删除索引,添加记录,然后重新索引:这作为一种解决方法很好,但当数据库在更新期间仍需要可用时不起作用。使数据库在 x 分钟/天 内完全无法访问是行不通的
- 将表格分成更小的子表格/文件:这将在短期内起作用,我已经尝试过。问题是我需要能够在查询时从整个历史记录中检索数据,这意味着最终我将达到 62 个表附件的限制。在临时表中附加、收集结果以及每次请求分离数百次似乎需要大量工作和开销,但如果没有其他选择,我会尝试。
-
Set
SQLITE_FCNTL_CHUNK_SIZE:我不会 C(?!),所以我宁愿不学习它只是为了完成它。不过,我看不到任何使用 Perl 设置此参数的方法。
更新
在Tim's suggestion 之后,索引导致越来越多 尽管 SQLite 声称它有能力,但插入时间很慢 在处理大型数据集时,我与以下进行了基准比较 设置:
- 插入的行数:1400 万
- 提交批量大小:50,000 条记录
-
cache_sizepragma: 10,000 -
page_sizepragma: 4,096 -
temp_storepragma: 内存 -
journal_modepragma: 删除 -
synchronouspragma: 关闭
在我的项目中,如下面的基准测试结果,创建了一个基于文件的临时表,并且 SQLite 的内置支持
用于导入 CSV 数据。然后附加临时表
到接收数据库并插入 50,000 行的集合
insert-select 声明。因此,插入时间不反映
文件到数据库插入时间,而是表到表插入
速度。考虑 CSV 导入时间会降低速度
降低 25-50%(一个非常粗略的估计,进口不需要很长时间
CSV 数据)。
随着表大小的增加,显然有索引会导致插入速度变慢。
从上面的数据中可以很清楚地看出,正确答案可以分配给Tim's answer,而不是SQLite 无法处理的断言。显然它可以处理大型数据集如果索引该数据集不属于您的用例。为此,我一直在使用 SQLite 作为日志系统的后端,现在 不需要 需要索引,所以我对我所经历的减速感到非常惊讶。
结论
如果有人发现自己想要使用 SQLite 存储大量数据并将其编入索引,using shards 可能是答案。我最终决定使用 MD5 哈希的前三个字符作为 z 中的唯一列来确定分配给 4,096 个数据库中的一个。由于我的用例本质上主要是归档,因此模式不会改变,查询也永远不需要分片遍历。数据库大小是有限制的,因为非常旧的数据将被减少并最终被丢弃,因此这种分片、杂注设置甚至一些de规范化的组合给了我一个很好的平衡,这将基于上述基准测试,保持插入速度至少为 10k 插入/秒。
【问题讨论】:
-
您是如何使用事务的?你配置了多大的页面缓存?
-
@CL。
cache_size设置为10000。所有插入都在一个事务中,每 50k 插入提交一次。这些值是在广泛测试后选择的,以找到最快的插入速度(35k-45k 插入/秒),但随着记录数量增加超过约 10m,速度会下降。 -
在这里超出您的具体问题:请问,您是使用 z_id 上的索引来查找单个记录还是选择范围?
-
@Tim 这是一个链接表,因此从
table_z中选择项目,然后通过此表通过z_id链接到table_y和table_x。因此,要回答您的问题,它有助于查找个人记录。 -
@veryhungrymike:在这种情况下,您可以查看一个非索引哈希表嵌套关系数据库,它可以让您立即找到指向 z_id 行以及链接到特定的 z_id 没有索引开销,并且随着索引的增长,在插入期间伴随的性能下降。对 z_id 具有最大变化(右加权)的数字赋予更大权重的方法会给您带来良好的分布。
标签: database optimization sqlite insert