将 django ORM 与多处理一起使用?
Posted
技术标签:
【中文标题】将 django ORM 与多处理一起使用?【英文标题】:Use django ORM with multiprocessing? 【发布时间】:2018-03-10 02:20:39 【问题描述】:我有一个 Django ORM 数据库(mysql 或 sqlite),并希望通过计算密集型操作来处理每一行。我现在拥有的是这样的:
entries = Entry.objects.filter(language='')
for e in entry:
e.language = detect_language(e.text)
e.save()
如果数据库是瓶颈,我会使用事务来加速它。但是,detect_language
函数花费的时间最多。我可以尝试多次并行运行脚本,但这会引入竞争条件。
我认为这可以通过 multiprocessing
使用 Pool.map()
来完成 - 主进程获取数据库条目,子进程运行 detect_language
。我不知道如何详细地做到这一点,例如是否将条目保存在子进程或主进程中。
在进程之间传递 ORM 对象时有什么需要注意的吗?您能否举一个简短的例子,如何将 ORM 与多处理一起使用?
我刚刚绑定了它,像这样的东西似乎工作正常。我仍然想知道这里是否有任何警告,或者这是否可以提高性能(例如批处理数据库更新):
def detect_and_save(obj):
obj.language = detect_language(obj.text)
obj.save()
with multiprocessing.Pool(processes=3) as pool:
pool.map(detect_and_save, entries)
【问题讨论】:
此操作是在线运行还是离线运行(例如在 Celery 任务中)? 离线,即在脚本中 (import myapp.wsgi
)。最终我可能会使用像 Celery 这样的东西,但目前为了测试我使用的是最简单的东西。
【参考方案1】:
-
您无需传递完整的 ORM 对象 - 您只需传递函数所需的参数并将其结果保存到 ORM 对象即可。
您可以使用 bulk_update(可从 Django 2.2 获得或作为 3rd party library)保存在单个查询中。
texts = [e.text for e in entries]
with multiprocessing.Pool() as pool:
languages = pool.map(detect_language, texts)
for e, l in zip(entries, languages):
e.language = l
Entry.objects.bulk_update(entries, ['language'])
【讨论】:
以上是关于将 django ORM 与多处理一起使用?的主要内容,如果未能解决你的问题,请参考以下文章