DoggoTheKing, была такая же задача на примерно таких же объёмах данных. order by rand показывал в 50 раз большую производительность, чем попытки оптимизировать.
class ProductQS(ByFlagsMixin, models.QuerySet):
def random(self, brand=None, amount=1):
qs = self.filter(brand=brand) if brand else self
return qs.order_by('?')[:amount]
# Когда продуктов станет куда больше, вариант
# ниже станет быстрее, а пока ORDER BY RAND()
# примерно в 50 раз быстрее.
#
# count = qs.count()
# offsets = sample(range(0, count), min(count, amount))
# return [qs[offset] for offset in offsets]