Кэш атрибутов в Django - в чем смысл? - PullRequest
2 голосов
/ 19 июля 2009

Я просто просматривал исходный код EveryBlock и заметил этот код в коде alerts / models.py:

    def _get_user(self):
    if not hasattr(self, '_user_cache'):
        from ebpub.accounts.models import User
        try:
            self._user_cache = User.objects.get(id=self.user_id)
        except User.DoesNotExist:
            self._user_cache = None
    return self._user_cache
    user = property(_get_user)

Я заметил этот паттерн вокруг группы, но я не совсем понимаю его использование. Вся идея состоит в том, чтобы убедиться, что при доступе к FK от self (self = alert object) вы только один раз получаете пользовательский объект из db? Почему бы вам просто не положиться на поле ForeignKey () db caching amd django? Я заметил, что определение модели содержит только идентификатор пользователя, а не поле внешнего ключа:

class EmailAlert(models.Model):
     user_id = models.IntegerField()
     ...

Любые идеи будут оценены.

Ответы [ 2 ]

2 голосов
/ 19 июля 2009

Хотя базы данных выполняют внутреннее кэширование, при возврате к БД каждый раз, когда вы хотите проверить значение связанного поля, все еще есть издержки - настройка запроса в Django, задержка сети при подключении к БД и возврат данные по сети, создание экземпляра объекта в Django и т. д. Если вы знаете, что данные не изменились за это время - и в контексте одного веб-запроса, вам, вероятно, все равно, если он есть - это делает намного больше смысл получать данные один раз и кэшировать их, а не запрашивать их каждый раз.

Одно из приложений, над которыми я работаю, имеет чрезвычайно сложную домашнюю страницу, содержащую огромный объем данных. Ранее он выполнял более 400 дБ запросов для рендеринга. Я реорганизовал его сейчас, так что он «использует» только 80, используя методы, очень похожие на те, которые вы опубликовали, и вам лучше поверить, что это дает огромный прирост производительности.

2 голосов
/ 19 июля 2009

Я не знаю, почему это IntegerField; похоже, это определенно должно быть поле ForeignKey (User) - из-за этого вы теряете такие вещи, как select_related () и другие.

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

Кроме того, для поиска требуется еще и обход базы данных. По моему опыту, с Django выполнение поиска элемента может занять от 0,5 до 1 мс для команды SQL на локальном сервере Postgresql плюс иногда нетривиальные издержки QuerySet. 1 мс - это много, если вам это не нужно - сделайте это несколько раз, и вы сможете превратить 30 мс запрос в 35 мс.

Если ваш SQL-сервер не является локальным, и у вас действительно есть обходные пути в сети, цифры становятся больше.

Наконец, люди обычно ожидают, что доступ к собственности будет быстрым; если они достаточно сложны, чтобы вызывать запросы SQL, кэширование результата обычно является хорошей идеей.

...