2011-02-28 97 views
2

是可以优化的Django不运行这么多疑问的是这样的Django的优化查询与循环

for student in Student.objects.all(): 
    for course in student.course_set.all(): 
     for grade in course.grade_set.filter(student=student): 
      # do stuff 

的查询量是学生的课程* *等级可以得到巨大的。

*编辑 从roseman的博客获得一些想法后的一种可能性。

for grade in student.grade_set.order_by('course', 'marking_period').select_related(): 
    if grade.marking_period_id in some_report_input: 
     # do stuff 

这只是一个片段,但基本上我换成for循环只有一个为我在乎(等级)等级的最后一个项目环有我需要的一切(学生,当然,标记时段)引用。使用诸如marking_period_id而不是grade.marking_period(做另一个查询)是关键。

折衷是代码可读性。我想筛选出成绩并根据标准进行组织。这从琐碎到复杂。

这绝不是一个通用的解决方案。我敢肯定,有些时候这根本无济于事。如果你知道更好的方法,请评论。

又如:

for student in students: 
    print student 
    for department in departments: 
    print department 
    failed_grades = Grade.objects.filter(course__department=department,course__courseenrollment__user=student,grade__lte=70) 
     for failed_grade in failed_grades: 
     print grade.course 
     print grade.grade 

学生获取课程就读。一门课程有一个部门。

+0

此处添加您的机型,所以我们可以了解他们是如何相互连接 – marianobianchi 2012-06-09 01:57:31

回答

-1

你可以使用select_related()它只会触发数据库一次。

在这个环节更多信息(Django的文档) http://docs.djangoproject.com/en/1.2/ref/models/querysets/#select-related

如果您发布的机型代码这将是有益的你怎么可以在你的情况

for x in Student.objects.select_related(): 
    do stuff with x.course.grade` 
+0

号这确实不与反向关系一起工作。 – 2011-02-28 19:11:44

+0

从Django 1.2开始,select_related用于反向关系,但只与OneToOne关系有关......但我认为你是对的。这个解决方案这次不会工作......也许在Grade.objects.select_related()中做'等级,然后做过滤器? – EroSan 2011-02-28 20:07:42

+0

我可以确认看着mysql的“状态”; select_related结果的查询数量完全相同。 – Bufke 2011-02-28 20:08:11

1

使用这样的一个例子和“做你的东西“代码ommit。这样,我们就可以了解如何在您的案例中进行有效的查询。

尽管如此,我认为this可能会有所帮助。它涵盖select_related没有的一些情况。请注意,prefetch_relatedDjango 1.4起可用,因此您可能需要升级到此版本才能使用它。

对于我们来说,在这里添加“do stuff”代码对于我们来说非常重要,如果它是相关的(并且我认为它会)在这里添加您的模型代码(只是字段声明可以) 。因为获取优化查询的方式取决于模型的相关方式以及如何使用查询集结果。

编辑:

以优化最后“为”您的最后一个例子,你可以这样做:

failed_grades = Grade.objects.filter(course__department=department,course__courseenrollment__user=student,grade__lte=70).select_related('course') 
for failed_grade in failed_grades: 
    print grade.course 
    print grade.grade 

在这个例子中,当你做grade.courseselect_related部分的查询缓存所有与筛选成绩相关的课程,因此您可以使用它们进行一次查询。因此,如果场模型只使用它自己的领域(我的意思是,如果你不显示在课程的统一方法的任何其他模型数据),你应该得到更好的性能(较少查询),在您的示例__unicode__方法。我不确定如何根据需要改进其他语句。但我认为这可以帮助你得到你想要的东西(也许我不理解你的车型太多,以帮助您更好)

+0

感谢您的回答。我还没有看到prefetch_related会有什么明显的帮助,但我需要更多地进行调查。 您可以查看完整的代码[这里](http://code.google.com/p/student-worker-relational-database/source/browse/ecwsp/sis/report.py)开始行237我我会试着想出一些比上面更完整的代码,而没有整个凌乱的源代码文件。 – Bufke 2012-06-08 16:06:54

+0

我想看看你的代码,我很害怕......如果你有200个多行的方法行'pod_report_grade',你有一个更大的问题优化查询前出席。请阅读django文档。制作[教程](https://docs.djangoproject.com/en/1.4/intro/tutorial01/)。再次重新开始,因为该代码是不可能的... – marianobianchi 2012-06-09 01:56:06

+0

是的,这真的很糟糕。它也有成千上万的用户,有时真实生活很糟糕。我提供了第二个例子。 – Bufke 2012-06-11 22:39:35