有很大的数据库文件的sqlite的性能特点是什么?

我知道sqlite在超大型的数据库文件中performance不佳,即使它们被支持(曾经有一个关于sqlite网站的评论,指出如果你需要大于1GB的文件大小,你可能要考虑使用企业rdbms。再也找不到了,可能与旧版本的sqlite有关)。

但是,为了我的目的,我想先了解一下在考虑其他解决scheme之前它究竟有多糟糕。

我正在谈论2 GB以上的千兆字节范围内的sqlite数据文件。 任何人有任何这方面的经验? 任何提示/想法?

所以我用sqlite做了一些testing,查看非常大的文件,并得出了一些结论(至less对于我的具体应用)。

testing涉及单个表或多个表的单个sqlite文件。 每个表格大约有8列,几乎所有的整数和4个指数。

这个想法是插入足够的数据,直到sqlite文件大约50GB。

单桌

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

这导致我得出结论,一个单独的,非常大的sqlite表将有插入问题,也可能是其他操作。

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

多个表

然后,我试着按时间分割数据,每天一张桌子。 原始1表的数据被分成〜700个表。

这种设置没有插入问题,随着时间的推移不需要更长的时间,因为每天都创build一个新的表格。

真空问题

正如i_like_caffeine指出的那样,VACUUM命令是一个问题,sqlite文件越大。 随着更多的插入/删除操作,磁盘上的文件碎片将变得更糟,因此目标是定期进行VACUUM优化文件并恢复文件空间。

然而,正如文件所指出的那样,数据库的完整副本是要做的真空,需要很长时间才能完成。 所以数据库越小,这个操作就会越快完成。

结论

对于我的具体应用,我可能会将数据分成几个db文件,每天一个,以获得最佳的真空性能和插入/删除速度。

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

我可能不得不监视每个文件的表大小以及速度将成为一个问题。

这真是太糟糕了,除了汽车真空之外,似乎还没有一种增量真空方法。 我无法使用它,因为我的真空目标是对文件进行碎片整理(文件空间不是什么大问题),而真空是不行的。 实际上,文档说明它可能会使分片变得更糟,所以我必须求助于定期对文件做一个完整的真空。

我们在我们的平台上使用50 GB +的DBS。 没有抱怨工作很好。 确保你做的一切正确! 你在使用预定义的语句吗? * SQLITE 3.7.3

  1. 交易
  2. 预先发言
  3. 应用这些设置(创build数据库之后)

    PRAGMA main.page_size = 4096; PRAGMA main.cache_size=10000; PRAGMA main.locking_mode=EXCLUSIVE; PRAGMA main.synchronous=NORMAL; PRAGMA main.journal_mode=WAL; PRAGMA main.cache_size=5000; 

希望这会帮助别人,在这里工作很好

我创build了3.5GB的SQLite数据库,没有明显的性能问题。 如果我没有记错,我认为SQLite2可能有一些下限,但我不认为SQLite3有任何这样的问题。

根据SQLite限制页面,每个数据库页面的最大大小是32K。 而数据库中的最大页面数是1024 ^ 3。 所以通过我的math来说,最大的尺寸是32TB。 我想你会击中SQLite的之前,你的文件系统的限制!

大部分花费48小时以上的原因是因为你的索引。 这是令人难以置信的更快:

1 – 删除所有索引2 – 全部插入3 – 再次创build索引

除了通常的build议:

  1. 拖放索引批量插入。
  2. 在大型交易中批量插入/更新。
  3. 调整缓冲区caching/禁用日志/ W PRAGMAs。
  4. 使用64位的机器(能够使用大量的caching)。
  5. [2014年7月添加]使用公用表expression式(CTE),而不是运行多个SQL查询! 需要SQLite版本3.8.3。

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

  1. 为了获得最大插入速度,请不要使用具有任何列约束的模式。 ( 以后根据需要更改表格 你不能用ALTER TABLE添加约束)。
  2. 优化你的模式来存储你所需要的。 有时这意味着在插入到数据库之前分解表和/或甚至压缩/转换数据。 一个很好的例子是将IP地址存储为(长)整数。
  3. 每个数据库文件一个表 – 最大限度地减less锁争用。 (如果你想拥有一个连接对象,请使用ATTACH DATABASE
  4. SQLite可以在同一列中存储不同types的数据(dynamictypes),使用这一点是有利的。

问题/评论欢迎。 😉

我认为关于sqlite缩放的主要抱怨是:

  1. 单进程写入。
  2. 没有镜像。
  3. 没有复制。

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

当使用vacuum命令时,我遇到了大型sqlite文件的问题。

我还没有尝试过auto_vacuumfunction。 如果您希望经常更新和删除数据,那么这是值得关注的。

以前在SQLite文档中有一个声明,数据库文件的实际大小限制是几十GB:s。 这主要是由于SQLite在开始事务时需要“分配脏页面的位图”。 因此数据库中的每个MB需要256字节的RAM。 插入50 GB的DB文件需要大量(2 ^ 8)*(2 ^ 10)= 2 ^ 18 = 256 MB的RAM。

但是从最近版本的SQLite开始,这已经不再需要了。 在这里阅读更多。