使用Django将数千条logging插入SQLite表的有效方法是什么?
我必须使用Django的ORM将8000多条logging插入SQLite数据库。 这个操作需要每分钟大约一次的cronjob运行。
目前我正在使用for循环遍历所有项目,然后逐个插入它们。
例:
for item in items: entry = Entry(a1=item.a1, a2=item.a2) entry.save()
什么是这样做的有效方式?
编辑:两个插入方法之间的一点点比较。
没有commit_manually装饰器(11245logging):
nox@noxdevel marinetraffic]$ time python manage.py insrec real 1m50.288s user 0m6.710s sys 0m23.445s
使用commit_manually装饰器(11245logging):
[nox@noxdevel marinetraffic]$ time python manage.py insrec real 0m18.464s user 0m5.433s sys 0m10.163s
注意:除了插入到数据库之外, testing脚本还执行一些其他操作(下载ZIP文件,从ZIP压缩文件中提取XML文件,parsingXML文件),因此执行所需的时间不一定代表插入所需的时间logging。
你想检查出django.db.transaction.commit_manually
。
http://docs.djangoproject.com/en/dev/topics/db/transactions/#django-db-transaction-commit-manually
所以它会是这样的:
from django.db import transaction @transaction.commit_manually def viewfunc(request): ... for item in items: entry = Entry(a1=item.a1, a2=item.a2) entry.save() transaction.commit()
哪个只会提交一次,而不是每个save()。
在django 1.3中引入了上下文pipe理器。 所以现在你可以用类似的方式使用transaction.commit_on_success()
from django.db import transaction def viewfunc(request): ... with transaction.commit_on_success(): for item in items: entry = Entry(a1=item.a1, a2=item.a2) entry.save()
在django 1.4中, bulk_create
被添加,允许你创build你的模型对象的列表,然后一次全部提交它们。
注意使用批量创build时,不会调用save方法。
>>> Entry.objects.bulk_create([ ... Entry(headline="Django 1.0 Released"), ... Entry(headline="Django 1.1 Announced"), ... Entry(headline="Breaking: Django is awesome") ... ])
在django 1.6中,引入了transaction.atomic ,意在替代现在的传统函数commit_on_success
和commit_manually
。
从django primefaces的文档 :
primefaces可用作装饰器:
from django.db import transaction @transaction.atomic def viewfunc(request): # This code executes inside a transaction. do_stuff()
作为上下文pipe理者:
from django.db import transaction def viewfunc(request): # This code executes in autocommit mode (Django's default). do_stuff() with transaction.atomic(): # This code executes inside a transaction. do_more_stuff()
批量创build在Django 1.4中可用:
https://django.readthedocs.io/en/1.4/ref/models/querysets.html#bulk-create
看看这个 。 它只能用于MySQL的开箱即用,但是有一些关于如何处理其他数据库的指针。
批量加载项目可能会更好 – 准备文件并使用批量加载工具。 这将比8000个单独的插入物高得多。
你应该看看DSE 。 我写了DSE来解决这些问题(大量插入或更新)。 使用django orm是一个死胡同,你必须用普通的SQL来完成,而DSE会为你处理大部分的问题。
托马斯
回答这个问题,特别是关于SQLite的问题,虽然我刚才已经证实bulk_create确实提供了巨大的提速,但SQLite有一个限制:“默认情况下是在一个批处理中创build所有的对象,除了SQLite,默认是这样的,每个查询最多使用999个variables。“
引用的内容来自文档— A-IV提供了一个链接。
我必须补充的是, 这个alpar的djangosnippets入口也似乎为我工作。 这是一个小包装,它将您要处理的大批量分成更小的批次,pipe理999个variables的限制。
我build议使用普通的SQL(而不是ORM),你可以用一个插入插入多行:
insert into A select from B;
只要结果与表A中的列匹配,并且不存在约束冲突,那么从 SQL的B部分中select可能会像您希望的那样复杂。
我遇到了同样的问题,我想不出没有这么多插入的方法。 我同意使用交易可能是解决这个问题的正确方法,但这里是我的破解:
def viewfunc(request): ... to_save = []; for item in items: entry = Entry(a1=item.a1, a2=item.a2) to_save.append(entry); map(lambda x: x.save(), to_save);