Python 正在聚合/优化对象.save()?
我正在开发导入功能,它允许用户从选定的csv文件创建django数据库模型 模型与外键和多对多字段相互关联。 有很多Python 正在聚合/优化对象.save()?,python,django,postgresql,Python,Django,Postgresql,我正在开发导入功能,它允许用户从选定的csv文件创建django数据库模型 模型与外键和多对多字段相互关联。 有很多 object.save() 和Object.objects.get(…)在我的代码中,我想这会导致它运行得很慢 当发生错误(例如完整性错误)时,我需要回滚数据库中的所有更改。所以我用 transaction.atomic 在我看来,这是一个很好的装饰 问题是,我的导入非常慢。解析包含约2000行的文件(可能会向我的数据库中添加约1000个对象)大约需要3分钟,这太长了 有没
object.save()
和Object.objects.get(…)
在我的代码中,我想这会导致它运行得很慢
当发生错误(例如完整性错误)时,我需要回滚数据库中的所有更改。所以我用
transaction.atomic
在我看来,这是一个很好的装饰
问题是,我的导入非常慢。解析包含约2000行的文件(可能会向我的数据库中添加约1000个对象)大约需要3分钟,这太长了
有没有办法让它更快?我读过
bulk_create
函数,但“它不适用于多对多关系”
如果这很重要,我正在使用postgresql
编辑:
文件结构如下所示:
subject_name
day [A/B] begins_at - ends_at;lecturer_info
然后是多行,如:
student_uid;student_info
好的,这是代码
def csv_import(market, csv_file):
lines = [line.strip().decode('utf-8') for line in csv_file.readlines()]
lines = [line for line in lines if line]
pattern = re.compile(r'[0-9]+;.+')
week_days = {
'monday': 0,
.
.
.
}
term, subject, lecturer, student = None, None, None, None
for number, line in enumerate(lines):
if not ';' in line:
subject = Subject(subject_id=number, name=line, market=market)
subject.save()
elif not pattern.match(line):
term_info, lecturer_info = line.split(';') # term_info - 'day begins_at - ends_at', lecturer_info - lecturer
term_info = term_info.replace(' - ', ' ').split()
term = Term(term_id=number, subject=subject, day=week_days[term_info[0]], begin_at=term_info[-2],
ends_at=term_info[-1])
if len(term_info) == 4:
term.week = term_info[1]
lecturer_info = lecturer_info.rsplit(' ', 1)
try:
lecturer = Lecturer.objects.get(first_name=lecturer_info[0], last_name=lecturer_info[1])
except Lecturer.DoesNotExist:
lecturer = Lecturer(first_name=lecturer_info[0], last_name=lecturer_info[1])
lecturer.save()
term.lecturer = lecturer
term.save()
else:
gradebook_id, student_info = line.split(';')
student_info = student_info.rsplit(' ', 1)
try:
student = TMUser.objects.get(uid=int(gradebook_id))
except TMUser.DoesNotExist:
student = TMUser(uid=int(gradebook_id), username='student'+gradebook_id, first_name=student_info[0],
last_name=student_info[1], password=make_password('passwd'), user_group='user')
student.save()
student.terms.add(term)
student.save()
这是一些伪代码,向您展示了缓存结果的基本概念:
cache = {}
for number, line in enumerate(lines):
...
elif not pattern.match(line):
...
term = Term(term_id=number, subject=subject, ...)
lecturer_id = (lecturer_info[0], lecturer_info[1]) #first name and last
if cache[lecturer_id]:
#retrieve from cache
lecturer = cache[lecturer_id]
else:
try:
lecturer = Lecturer.objects.get(first_name= lecturer_id[0], last_name= lecturer_id[1])
except Lecturer.DoesNotExist:
lecturer = Lecturer(first_name= lecturer_id[0], last_name= lecturer_id[1])
lecturer.save()
#add to cache
cache[lecturer_id] = lecturer
term.lecturer = lecturer
term.save()
#etc.
哪一位慢?解析文件还是加载到数据库?你能告诉我你是怎么装的吗?哦,对不起,我没提这个。我想从数据库中保存/选择。A还没有运行探查器,但我从代码中删除了所有django的引用,使用简单类而不是django.models,并尝试解析同一个文件-然后花了几毫秒。。。如果您愿意,我可以编辑我的帖子并粘贴代码。代码将有所帮助,因为在不知道用例的情况下没有有效答案。我粘贴了代码,希望这将对您有所帮助。基本上,您的代码在不缓存结果的情况下进行大量查找。每次查询或创建一个术语或讲师时,请将结果保存在dict中。然后,当您链接它们或创建其他内容时,您可以从dict中获取对象,而无需额外查询。我第一次了解您;)我也会对用户这样做,因为他们经常重复。但问题是——除了这个,还有其他选择吗?我的意思是,一些django功能优化了这些任务?我怀疑。您正在优化数据库操作。批量操作可能仍然会对您有所帮助,但是您需要通过对CSV结果进行分组来对插入内容进行分组(您可以使用Pandas很好地完成这项工作)。如果您可以使用连接查询,这可能会有所帮助,但在您的情况下可能不会太多。缓存结果,每次插入至少会优化一次往返。速度仍然很慢,但有点帮助,谢谢。在这种情况下,请尝试将CSV解析为某种结构(dict、dataframe等),并通过组执行查询/插入。否则,您将不得不查看数据库索引,看看它们是否得到了优化。