2020年更新,大约11年前这个问题被发布,后来被关闭,阻止了更新的答案。

这里写的几乎都过时了。曾几何时,sqlite被限制在内存容量或2gb的存储空间(32位)或其他流行的数字…那是很久以前的事了。

官方限制列在这里。实际上,只要有可用的存储空间,sqlite就可能工作。它适用于比内存大的数据集,它最初是在内存很薄的时候创建的,从一开始就非常重要。

存储100gb的数据绝对没有问题。它可能可以很好地存储TB,但最终这是你需要质疑SQLite是否是最好的工具,你可能想要一个完整的数据库的功能(远程客户端,并发写入,只读副本,分片等…)


原:

我知道即使sqlite支持超大的数据库文件,sqlite也不能很好地处理它们(sqlite网站上曾经有一条评论说,如果你需要超过1GB的文件大小,你可能要考虑使用企业rdbms。再也找不到它了,可能与sqlite的旧版本有关)。

然而,出于我的目的,我想在考虑其他解决方案之前了解它到底有多糟糕。

我说的是从2GB开始的千兆字节范围的sqlite数据文件。 有人有这方面的经验吗?任何建议/想法吗?


当前回答

因此,我使用sqlite对非常大的文件进行了一些测试,并得出了一些结论(至少对于我的特定应用程序)。

测试涉及单个sqlite文件,其中包含单个表或多个表。每个表大约有8列,几乎都是整数,还有4个索引。

我们的想法是插入足够的数据,直到sqlite文件达到50GB左右。

单表

我尝试将多行插入到只有一个表的sqlite文件中。当文件大约7GB时(对不起,我不能具体说明行数),插入花费的时间太长了。我曾估计插入所有数据的测试需要24小时左右,但即使在48小时后也没有完成。

这使我得出结论,一个非常大的sqlite表在插入和其他操作方面都会有问题。

我想这并不奇怪,随着表变大,插入和更新所有索引需要更长的时间。

多个表

然后,我尝试将数据按时间分割到几个表中,每天一个表。原始1个表的数据被分割为~700个表。

这种设置没有插入问题,随着时间的推移,它不会花费更长的时间,因为每天都会创建一个新表。

真空问题

正如i_like_caffeine所指出的,sqlite文件越大,VACUUM命令就会产生问题。随着插入/删除操作的增加,磁盘上文件的碎片会变得更糟,因此目标是定期使用VACUUM来优化文件并恢复文件空间。

然而,正如文档所指出的,数据库的完整副本是做真空的,需要很长时间才能完成。因此,数据库越小,该操作完成的速度就越快。

结论

对于我的特定应用程序,我可能会将数据分割到几个db文件中,每天一个,以获得最佳的真空性能和插入/删除速度。

这使查询变得复杂,但对我来说,能够索引这么多数据是值得的。另一个优点是,我可以删除整个db文件来删除一天的数据(这是我的应用程序的常见操作)。

我可能还要监视每个文件的表大小,以查看速度何时会成为问题。

除了自动真空,似乎没有增量真空方法,这太糟糕了。我不能使用它,因为我对真空的目标是整理文件(文件空间不是大问题),这是自动真空做不到的。事实上,文档表明这可能会使碎片化更糟,所以我必须定期对文件进行完全真空处理。

其他回答

我们在我们的平台上使用的是50gb以上的DBS。没有抱怨很有效。 确保你做的每件事都是正确的!您是否使用预定义语句? * SQLITE 3.7.3

交易 预先发表的声明 应用这些设置(在创建DB之后) 编译指示主要。Page_size = 4096; 编译指示main.cache_size = 10000; 编译指示main.locking_mode =独家; 编译指示main.synchronous =正常; 编译指示main.journal_mode =细胞膜; 编译指示main.cache_size = 5000;

希望这将帮助其他人,在这里工作得很好

在SQLite文档中曾经有一个声明,数据库文件的实际大小限制是几十GB:s。这主要是因为当您启动事务时,SQLite需要“分配脏页面的位图”。因此,数据库中每MB需要256字节的RAM。插入一个50gb的db文件需要一个巨大的(2^8)*(2^10)=2^18=256 MB的RAM。

但是在SQLite的最新版本中,不再需要这样做了。点击这里阅读更多。

因此,我使用sqlite对非常大的文件进行了一些测试,并得出了一些结论(至少对于我的特定应用程序)。

测试涉及单个sqlite文件,其中包含单个表或多个表。每个表大约有8列,几乎都是整数,还有4个索引。

我们的想法是插入足够的数据,直到sqlite文件达到50GB左右。

单表

我尝试将多行插入到只有一个表的sqlite文件中。当文件大约7GB时(对不起,我不能具体说明行数),插入花费的时间太长了。我曾估计插入所有数据的测试需要24小时左右,但即使在48小时后也没有完成。

这使我得出结论,一个非常大的sqlite表在插入和其他操作方面都会有问题。

我想这并不奇怪,随着表变大,插入和更新所有索引需要更长的时间。

多个表

然后,我尝试将数据按时间分割到几个表中,每天一个表。原始1个表的数据被分割为~700个表。

这种设置没有插入问题,随着时间的推移,它不会花费更长的时间,因为每天都会创建一个新表。

真空问题

正如i_like_caffeine所指出的,sqlite文件越大,VACUUM命令就会产生问题。随着插入/删除操作的增加,磁盘上文件的碎片会变得更糟,因此目标是定期使用VACUUM来优化文件并恢复文件空间。

然而,正如文档所指出的,数据库的完整副本是做真空的,需要很长时间才能完成。因此,数据库越小,该操作完成的速度就越快。

结论

对于我的特定应用程序,我可能会将数据分割到几个db文件中,每天一个,以获得最佳的真空性能和插入/删除速度。

这使查询变得复杂,但对我来说,能够索引这么多数据是值得的。另一个优点是,我可以删除整个db文件来删除一天的数据(这是我的应用程序的常见操作)。

我可能还要监视每个文件的表大小,以查看速度何时会成为问题。

除了自动真空,似乎没有增量真空方法,这太糟糕了。我不能使用它,因为我对真空的目标是整理文件(文件空间不是大问题),这是自动真空做不到的。事实上,文档表明这可能会使碎片化更糟,所以我必须定期对文件进行完全真空处理。

除了通常的建议:

为批量插入删除索引。 在大型事务中批量插入/更新。 调优缓冲区缓存/禁用日志/w PRAGMAs。 使用64位机器(以便能够使用大量缓存™)。 [2014年7月添加]使用公共表表达式(CTE)而不是运行多个SQL查询!需要SQLite 3.8.3版。

我从SQLite3的经验中学到了以下几点:

For maximum insert speed, don't use schema with any column constraint. (Alter table later as needed You can't add constraints with ALTER TABLE). Optimize your schema to store what you need. Sometimes this means breaking down tables and/or even compressing/transforming your data before inserting to the database. A great example is to storing IP addresses as (long) integers. One table per db file - to minimize lock contention. (Use ATTACH DATABASE if you want to have a single connection object. SQLite can store different types of data in the same column (dynamic typing), use that to your advantage.

问题/欢迎发表评论。: -)

我有一个7GB的SQLite数据库。 使用内部连接执行特定查询需要2.6秒 为了加快速度,我尝试添加索引。根据我添加的索引,有时查询会下降到0.1秒,有时会上升到7秒。 我认为在我的情况下的问题是,如果一个列是高度重复的,然后添加索引降低性能:(