django querysets + memcached: лучшие практики - PullRequest
16 голосов
/ 30 сентября 2011

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

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

  • набор запросов (объект python) имеет / поддерживает свой собственный кеш
  • доступ к базе данных ленив; даже если queryset.count равен 1000, если я сделаю object.get для 1 записи, то база данных будет только Доступ к этой записи один раз.
  • при доступе к представлению django через apache prefork MPM, каждый раз, когда конкретный экземпляр X демона в конечном итоге вызывает конкретное представление, которое включает в себя что-то как "tournres_qset = TournamentResult.objects.all ()", это каждый раз приводит к новому объекту tournres_qset создается То есть все, что могло быть кэшировано внутри объектом python 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, который всегда будет начинаться с нуля, с пустым локальным кеш запросов; доступ к базе данных всегда будет происходить.)

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

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

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

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

1 Ответ

24 голосов
/ 01 октября 2011

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

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

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

Обновлено, чтобы отвечать на вопросы в комментарии

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

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

...