ecb*_*tln 7 django django-models django-queryset
我在Django中设置了一个复杂的数据库模型,我必须根据过滤数据进行大量计算.我有一个Test对象,一个TestAttempt对象和一个UserProfile对象(外键返回测试,外键返回用户配置文件).我运行的方法是TestAttempt计算测试分数(基于用户提供的多个选项与每个测试相关的正确答案).然后我运行的另一种方法是Test根据每个关联TestAttempt的方法计算平均测试分数.但有时候我只希望平均值基于TestAttempt与特定集合链接的相关联的子集UserProfiles.因此,不要以这种方式计算特定测试的平均测试分数:
[x.score() for x in self.test_attempts.all()]
Run Code Online (Sandbox Code Playgroud)
然后平均这些值.我做这样的查询:
[x.score() for x in self.test_attempts.filter(profile__id__in=user_id_list).all()]
Run Code Online (Sandbox Code Playgroud)
其中user_id_list是UserProfile id的特定子集,我希望以列表的形式找到平均测试分数.我的问题是:如果user_id_list确实是整个集合UserProfile(因此过滤器将返回相同的self.test_attempts.all())并且大部分时间都是这种情况,检查这种情况是否有效,如果是,则不执行过滤器?或__in查找是否足够有效,即使user_id_list包含所有用户,运行过滤器也会更有效.另外,我是否需要担心生成的test_attempts distinct()?或者他们不可能用我的queryset结构重复复制?
编辑:对于任何有兴趣查看原始SQL查询的人来说,它看起来像这样没有过滤器:
SELECT "mc_grades_testattempt"."id", "mc_grades_testattempt"."date",
"mc_grades_testattempt"."test_id", "mc_grades_testattempt"."student_id" FROM
"mc_grades_testattempt" WHERE "mc_grades_testattempt"."test_id" = 1
Run Code Online (Sandbox Code Playgroud)
这与过滤器:
SELECT "mc_grades_testattempt"."id", "mc_grades_testattempt"."date",
"mc_grades_testattempt"."test_id", "mc_grades_testattempt"."student_id" FROM
"mc_grades_testattempt" INNER JOIN "mc_grades_userprofile" ON
("mc_grades_testattempt"."student_id" = "mc_grades_userprofile"."id") WHERE
("mc_grades_testattempt"."test_id" = 1 AND "mc_grades_userprofile"."user_id" IN (1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
请注意,数组(1,2,3)只是一个例子
简短的答案是 \xe2\x80\x93 基准。在不同的情况下进行测试并测量负载。这将是最好的答案。
这里不能有重复的。
检查两种情况真的有问题吗?这是假设的代码:
\n\ndef average_score(self, user_id_list=None):\n qset = self.test_attempts.all()\n if user_id_list is not None:\n qset = qset.filter(profile__id__in=user_id_list)\n scores = [x.score() for x in qset]\n # and compute the average\nRun Code Online (Sandbox Code Playgroud)我不知道score方法是做什么的,但是你不能计算数据库级别的平均值吗?它会给你带来更显着的性能提升。
并且不要忘记缓存。
| 归档时间: |
|
| 查看次数: |
2138 次 |
| 最近记录: |