django - 并行线程不会增加具有 Django 性能的多个数据库插入

标签 django postgresql

我正在使用 Python 和 Django(使用 CLI,所以根本没有 Web 服务器)对 PostgreSQL 数据库执行成千上万次插入操作。 插入的对象已经在内存中,我从 FIFO 队列中一个一个地弹出它们(使用 Python 的 native https://docs.python.org/2/library/queue.html )

我所做的基本上是:

args1, args2 = queue.get()
m1, _ = Model1.objects.get_or_create(args1)
Model2.objects.create(m1, args2)

我正在考虑一种更快地执行此操作的方法,即生成更多可以并行执行此操作的线程。令我惊讶的是,性能实际上略有下降......我期待与线程数量相关的几乎线性改进......不确定发生了什么......

是否缺少某些特定于数据库的东西,是否有表锁在运行时阻塞线程? 还是与每个线程在运行时只能原子地访问单个数据库连接有关?

我在 Debian Jessie 上使用 apt-get 安装了 PostgreSQL (9.3) 和 Django (1.7.7) 的标准配置。 我还尝试了 4 个线程,这与我机器上可用的 CPU 数量相同。

最佳答案

这里发生了一些事情。

首先,您正在使用非常高级的 ORM 方法(get_or_createcreate)。这些通常不适合批量操作,因为这样的方法往往会产生大量开销来提供良好的 API,并且还会做额外的工作以防止用户太容易搬起石头砸自己的脚。

其次,您对 queue 的谨慎使用会在多个方面适得其反:

  • 由于 django 在 autocommit mode 中运行默认情况下,每个数据库操作都在其自己的事务中执行。由于这是一个相对昂贵的操作,这也会导致不必要的开销。
  • 单独插入每个对象也会导致数据库和 Django 之间的来回通信更多,这会再次产生开销,从而降低速度。

第三,使用多线程甚至更慢的原因是 python 有一个 GIL(全局解释器锁)。这可以防止多个线程同时执行 Python 代码。网络上有很多关于 GIL 的原因和方式的资料,以及在什么情况下可以做什么来缓解它。有个不错的summary by Dave Beazly如果您有兴趣了解更多有关 GIL 的信息,可以帮助您入门。

此外,我通常建议不要使用任何语言从多个线程执行大量插入,因为 - 根据您的数据库和数据模型 - 这也可能由于可能需要锁定而导致数据库内部速度变慢。

现在您的问题有很多解决方案,但我建议您从一个简单的开始: Django 实际上提供了一个方便的低级接口(interface)来批量创建模型,称为 bulk_create() 很合适。 .我建议删除所有花哨的队列和线程代码,并尽可能直接地使用此接口(interface)处理您已有的数据。

如果这对您的情况来说还不够,一种可能的替代方法是从数据生成一个 INSERT INTO 语句并直接在数据库上执行它。

关于django - 并行线程不会增加具有 Django 性能的多个数据库插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31062124/

相关文章:

postgresql - 使用 bitcoind RPC 和 API 填充 PostgreSQL 数据库

postgresql - 错误 : current transaction is aborted, 命令在事务 block 结束之前被忽略 --- 从 Aqua studio 导出数据

node.js - Sequelize 和 WITH HOLD 游标

sql - 匹配相似的邮政编码

django - 无法安装 psycopg2-binary

python - 在 Django 中将 easy-thumbnails(或其他第 3 方库)与 jinja2 一起使用

python - "Apps aren' t 已加载 "and "django.core.exceptions.ImproperlyConfigured“在 Django 中?

Django,获取scheme(http或https),预request.scheme实现

mysql - 如何处理意外的 MySQL 数据库引擎更改?

python - Django Selenium 测试,创建用户并检查登录