Подтвердить что ты не робот

Django querysets + memcached: лучшие практики

Попытка понять, что происходит во время низкоуровневого кэша django() В частности, подробности о том, какая часть набора запросов хранится в memcached.

Во-первых, я правильно интерпретирую django-документы?

  • набор запросов (объект python) имеет/поддерживает свой собственный кеш
  • доступ к базе данных ленив; даже если значение queryset.count равно 1000, если я делаю object.get для 1 записи, тогда dbase будет только один раз, для этой 1 записи.
  • при доступе к представлению django через apf prefork MPM, каждый раз, когда конкретный экземпляр X-демона вызывает вызов определенного представления, которое включает в себя что-то например "tournres_qset = TournamentResult.objects.all()", это приведет к тому, что каждый раз в новом объекте tournres_qset создается. То есть все, что может быть кэшировано внутри страны по объекту pwnon tournres_qset из предыдущего (tcp/ip) посещения, вообще не используется новым запросом tournres_qset.

Теперь вопросы о сохранении вещей в memcached в представлении. Скажем, я добавляю что-то вроде этого в верхней части представления:

tournres_qset = cache.get('tournres', None)
if tournres_qset is None:
    tournres_qset = TournamentResult.objects.all()
    cache.set('tournres', tournres_qset, timeout)
# now start accessing tournres_qset
# ...

Что хранится во время cache.set()?

  • Получается ли сериализация и сохранение всего запроса (объекта python)?

  • Поскольку набор запросов еще не использовался для получения каких-либо записей, это просто пустая трата времени, поскольку на самом деле содержание конкретных записей сохраняются в memcache? (Любые будущие запросы получат запрос объект из memcache, который всегда будет начинать новый, с пустым локальным кеш запросов; доступ к dbase всегда будет иметь место.)

  • Если приведенное выше значение истинно, тогда я должен просто повторно сохранить запрос в конце представления, после того, как он использовался во всех некоторые записи, которые приведут к обновлению локального кеша запроса, и который всегда должен быть повторно сохранен в memcached? Но тогда это всегда приведет к еще раз сериализации объекта запроса. Так много для ускорения.

  • Или же cache.set() принудительно перенастраивает объект queryset для итерации и доступ из dbase всех записей, которые также будут сохранены в Memcache? Все будет сохранено, даже если доступ только открывается подмножество набора запросов?

Я вижу ловушки во всех направлениях, что заставляет меня думать, что я нахожусь непонимая целую кучу вещей.

Надеюсь, что это имеет смысл и ценят разъяснения или указатели на некоторые "стандартные" рекомендации. Спасибо.

4b9b3361

Ответ 1

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

Обратите внимание, что третья точка в вашем исходном наборе не совсем правильная, поскольку это не имеет никакого отношения к Apache или предпрохождению. Это просто, что представление является функцией, подобной любой другой, и все, что определено в локальной переменной внутри функции, выходит за пределы области действия, когда эта функция возвращается. Таким образом, набор запросов, определенный и оцениваемый внутри представления, выходит из области видимости, когда представление возвращает ответ, а новый будет создан при следующем вызове вида, то есть в следующем запросе. Это тот случай, который вы используете Django.

Однако, и это важно, если вы сделаете что-то вроде того, что задаете свой запрос на глобальную (модульную) переменную, он будет сохраняться между запросами. Большинство способов, которыми Django обслуживается, и это, безусловно, включает mod_wsgi, сохранить процесс для многих запросов до его утилизации, поэтому значение запроса будет одинаковым для всех этих запросов. Это может быть полезно в качестве своего рода кэша для транзакций, но трудно получить правильное решение, потому что вы не представляете, как долго длится процесс, а другие процессы, вероятно, будут выполняться параллельно, у которых есть свои собственные версии этой глобальной переменной.

Обновлено для ответа на вопросы в комментарии

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

Но всякая операция filter() в наборе запросов, даже одна, которая уже была оценена, является другим ударом базы данных. Это потому, что это модификация базового SQL-запроса, поэтому Django возвращается к базе данных - и возвращает новый запрос с собственным внутренним кешем.