эффективность django __in lookup для querysets

У меня есть сложная модель базы данных, настроенная в Django, и мне нужно сделать ряд вычислений на основе данных фильтра. У меня есть объект Test, объект TestAttempt и объект UserProfile (с внешним ключом к test и внешним ключом к userprofile). Есть метод, который я запускаю на TestAttempt, который вычисляет оценку теста (основанную на количестве вариантов, предложенных пользователем, по сравнению с правильными ответами, связанными с каждым тестом). И еще один метод, который я запускаю на Test и который вычисляет средний балл теста на основе каждого из связанных с ним TestAttempt Но иногда мне нужно среднее значение на основе только заданного подмножества связанных TestAttempt, которые связаны с определенным набором UserProfiles. Поэтому вместо того, чтобы вычислять средний тестовый балл для конкретного теста таким образом:

[x.score() for x in self.test_attempts.all()]

и затем усреднять эти значения. Я делаю такой запрос:

[x.score() for x in self.test_attempts.filter(profile__id__in=user_id_list).all()]

где user_id_list - это определенное подмножество идентификаторов UserProfile, для которых я хочу найти средний тестовый балл в виде списка. Мой вопрос заключается в следующем: если user_id_list - это действительно весь набор UserProfile (поэтому фильтр вернет то же самое, что и self.test_attempts. all()) и в большинстве случаев так и будет, стоит ли проверять этот случай, и если да, то не выполнять фильтр вообще? Или __in поиск достаточно эффективен, что даже если user_id_list содержит всех пользователей, эффективнее будет запустить фильтр. Также, нужно ли мне беспокоиться о том, чтобы результирующие test_attempts были distinct()? Или они не могут оказаться дубликатами с учетом структуры моего набора запросов?

EDIT: Для тех, кому интересно посмотреть на необработанный 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

и вот так с фильтром:

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))

обратите внимание, что массив (1,2,3) - это просто пример

7
задан ecbtln 12 January 2012 в 03:40
поделиться