我正试着Riot API challenge,我试图将Django用作PythonAnywhere.com托管的后端。
我已经设置了一个使用类似于下面结构的数据库
class MatchDetails(models.Model):
# Data fields
class Participant(models.Model):
match = models.ForeignKey(MatchDetails)
# Data fields
class Timeline(models.Model):
participant = models.ForeignKey(Participant)
# Data fields
# More fields, most with MatchDetails as foreign key.
我编写了一个检索和存储数据的功能,现在我已经存储了近4万个游戏,每个游戏有10个参与者。我的目标是从这些数据中提取一些统计数据,我基本上做了类似的事情:
allMatches = MatchDetails.objects.all()
for m in allMatches:
participants = m.participant_set.all()
for p in participants:
# Increment some values
# save the result to the database
目前需要2个多小时。
2015-04-11 03:47:35 - 完成任务,耗时7942.00秒,返回 代码是0。
这是一段荒谬的时间,不是吗?我有办法加快速度吗?
我尝试使用迭代器,我也尝试使用.value_list和.all.values()来迭代,但我无法通过这种方式获取通过外键相关的对象。
How do I speed up iteration of a large dataset in Django
使用value_list时,有什么方法可以访问我的外键对象吗?或者我还能做些什么来加快速度?任何指针将不胜感激。
感谢阅读!
答案 0 :(得分:1)
此时的最佳优化是使用prefetch_related()
:
allMatches = MatchDetails.objects.prefetch_related('participant_set')
for m in allMatches:
for p in m.participant_set.all():
# Increment some values
# save the result to the database
这会将您的查询数量从大约40 000减少到2。
答案 1 :(得分:0)
您可以尝试使用prefetch related加快速度。
此外,在您的values_list中,您可以获得所需的相关对象所需的属性,例如" foreign_key_relation_name__attribute"。
使用" iterator()"如果只迭代一次查询集,这也是一种提高速度的好方法。
你的"如何将结果保存到数据库"码?如果您使用update()批量保存所有项目而不是逐个保存每个项目,那么您也将提高速度。
答案 2 :(得分:0)
取决于两个因素 - 您正在更新的是什么,以及如果您正在运行Django 1.8 - 您不必遍历所有内容。
from django.db.models import F
m.participant_set.update(some_field=F('some_field')*10)
这会将参与者模型中的所有some_field
更新为其当前值乘以10,这比迭代所有行并每行执行更新要快几个数量级。
值得记住的是,如果你覆盖了Participant.save() - 方法,它将不会被调用,并且保存信号也不会被发送。