Почему Django получает список результатов из query_set слишком поздно?

Я изучаю вопрос о Django ORM. Я не смог найти ответ в поиске, но буду благодарен, если кто-нибудь подскажет мне связанный сайт.

Моя модель выглядит следующим образом. У пользователя1 есть 2 счета, и 500,000 транзакций принадлежат одному из счетов.

class Account(models.Model):
    class Meta:
        db_table = 'account'
        ordering = ['created_at']
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    account = models.CharField(max_length=20, null=False, blank=False, primary_key=True)
    balance = models.PositiveBigIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class AccountTransaction(models.Model):
    class Meta:
        db_table = 'account_transaction'
        ordering = ['tran_time']
        indexes = [
            models.Index(fields=['tran_type', 'tran_time', ]),
        ]
    account = models.ForeignKey(Account, on_delete=models.CASCADE)
    tran_amt = models.PositiveBigIntegerField()
    balance = models.PositiveBigIntegerField()
    tran_type = models.CharField(max_length=10, null=False, blank=False)
    tran_detail = models.CharField(max_length=100, null=True, default="")
    tran_time = models.DateTimeField(auto_now_add=True)

Время выполнения запроса для вышеуказанной модели следующее.

start = time.time()
rs = request.user.account_set.all().get(account="0000000010").accounttransaction_set.all()
count = rs.count()
print('>>all')
print(time.time() - start)  # 0.028000831604003906

start = time.time()
q = Q(tran_time__date__range = ("2000-01-01", "2000-01-03"))
rs = request.user.account_set.all().get(account="0000000010").accounttransaction_set.filter(q)
print('>>filter')
print(time.time() - start)  # 0.0019981861114501953

start = time.time()
result = list(rs)
print('>>offset')
print(time.time() - start)  # 5.4373579025268555

Результат запроса_set - всего около 3500 записей. (Из 500 000 записей было выбрано 3500). Я сделал ряд вещей, например, установил смещение на результат (rs) query_set, но все равно требуется много времени, чтобы получить фактическое значение из query_set. Я знаю, что представление загружает данные при приближении к фактическим значениям, таким как count(), но что я сделал не так?

From https://docs.djangoproject.com/en/4.1/topics/db/queries/#querysets-are-lazy:

QuerySet ленивы - акт создания QuerySet не включает в себя никакой активности в базе данных. Вы можете складывать фильтры вместе хоть целый день, и Django не будет выполнять запрос до тех пор, пока QuerySet не будет оценивается. Взгляните на этот пример:

q = Entry.objects.filter(headline__startswith="What")
q = q.filter(pub_date__lte=datetime.date.today())
q = q.exclude(body_text__icontains="food")
print(q)

Хотя это выглядит как три обращения к базе данных, на самом деле это обращение к базе данных только один раз, в последней строке. базе данных только один раз, в последней строке (print(q)). В общем случае результаты набора запросов не извлекаются из базы данных, пока вы не "попросите" о них. Когда вы это делаете, QuerySet оценивается путем обращения к базе данных. Подробнее о том, когда именно происходит оценка, см. Когда наборы запросов оцениваются.

В вашем примере база данных попадает в базу только при вызове list(rs), вот почему это занимает так много времени.

Вернуться на верх