带有批量插入的 peewee 进入 sqlite db 非常慢

peewee with bulk insert is very slow into sqlite db

我正在尝试使用 peewee 对 sqlite 数据库进行大规模批量插入。我正在使用 atomic 但性能仍然很糟糕。我正在插入大约 2500 行的块中的行,并且由于 我一次插入大约 200 行。这是代码:

with helper.db.atomic():
   for i in range(0,len(expression_samples),step):
      gtd.GeneExpressionRead.insert_many(expression_samples[i:i+step]).execute()

而列表 expression_samples 是包含 GeneExpressionRead 模型的适当字段的字典列表。我已经为这个循环计时,它需要 2-8 秒的时间来执行。我有数百万行要插入,按照我现在编写代码的方式,可能需要 2 天才能完成。根据 this post, there are several pragmas that I have set in order to improve performance. This also didn't really change anything for me performance wise. Lastly, as per this test on the peewee github page 应该可以非常快地插入许多行(0.3364 秒内约 50,000 行),但似乎作者使用原始 sql 代码来获得此性能。有没有人能够使用 peewee 方法进行如此高性能的插入?

编辑:没有意识到 peewee 的 github 页面上的测试是针对 MySQL 插入的。可能适用也可能不适用于这种情况。

在所有使用 atomic 的代码作为上下文管理器出现的文档中,它被用作函数。由于听起来您从未在 exit 块中看到 exit 块,因此您可能没有看到关于没有 __exit__ 方法的错误。

你能试试with helper.db.atomic():吗?

atomic() 正在开始交易。如果没有打开的事务,插入会慢得多,因为每次写入都必须进行一些昂贵的簿记,而不是只在开始和结束时进行。

编辑

由于开始问题的代码已更改,我能否提供有关您要插入的 table 的更多信息?大吗,有多少指数?

由于这是 SQLite,您只是在写入一个文件,但您知道该文件是在本地磁盘上还是在网络安装的驱动器上吗?我遇到过这样的问题,因为我试图插入 NFS 上的数据库。

Mobius 试图在评论中提供帮助,但其中有很多错误信息。

  • Peewee 在您创建 table 时为外键创建索引。当前支持的所有数据库引擎都会出现这种情况。
  • 打开外键 PRAGMA 会减慢速度,否则为什么会这样?
  • 为获得最佳性能,请勿在要批量加载的 table 上创建任何索引。加载数据,然后 创建索引。这对数据库来说要少得多。
  • 如您所述,禁用批量加载的自动增量会加快速度。

其他信息:

  • 使用 PRAGMA journal_mode=wal;
  • 使用 PRAGMA 同步=0;
  • 使用 PRAGMA locking_mode=EXCLUSIVE;

这些是加载一堆数据的一些很好的设置。查看 sqlite 文档以获取更多信息:

http://sqlite.org/pragma.html