django __in查询查询集的效率

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)只是一个例子

DrT*_*rsa 2

    \n
  1. 简短的答案是 \xe2\x80\x93 基准。在不同的情况下进行测试并测量负载。这将是最好的答案。

  2. \n
  3. 这里不能有重复的。

  4. \n
  5. 检查两种情况真的有问题吗?这是假设的代码:

    \n\n
    def 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\n
    Run Code Online (Sandbox Code Playgroud)
  6. \n
  7. 我不知道score方法是做什么的,但是你不能计算数据库级别的平均值吗?它会给你带来更显着的性能提升。

  8. \n
  9. 并且不要忘记缓存。

  10. \n
\n