【问题标题】:Django QuerySets and cacheDjango QuerySets 和缓存
【发布时间】:2016-09-08 08:44:39
【问题描述】:

我的一些对象管理器中有一个从 db 获取数据的方法:

def products(self, offset=None)

如果没有offset 传递,它只是返回所有 个对象(大约5000 个,不多)。如果有offest,它会返回带有偏移量的对象。

此方法在应用程序生命周期中使用了很多。我想以某种方式缓存其结果是合理的。

我的问题是:functools.lru_cache 会完成这项工作还是应该考虑使用 Django 的缓存?或者也许我不应该过早地考虑它?

【问题讨论】:

    标签: django caching optimization query-optimization


    【解决方案1】:

    这取决于您尝试优化的位置。 Django caching(不要与 QuerySet caching 混淆,这是他们需要注意的行为的一个重要方面)当您想要跳过提供动态页面的动态部分时使用。因此,使用这些时的主要想法是(以及持续多长时间)我呈现给用户的内容不会改变?在优化您对产品的调用方面,functools.lru_cache 将为您提供一个简单的内存缓存,但您主要关心的是使用 cache_clear() 破坏缓存的频率。完整回答您的问题:

    缓存通常不会有什么坏处,但如果您没有注意到性能问题,它也可能没有必要。如果您担心在使用 products() 时不会对数据库造成太多影响,您可以利用 lru_cache 并且您需要根据数据的性质决定何时/是否缓存 bust。话虽如此,数据库已针对此类检索进行了高度优化,根据您的应用程序,可能不值得额外的逻辑。此外,您还需要考虑您现在在内存中保留了多少持久存储中的内容,以及这种权衡是否值得。

    如果您不断地重新生成相同的页面以呈现给用户,请考虑使用 Django 缓存。跳过 products() 之前的步骤,只有在它们确实稳定一段时间后才会有所帮助。

    就个人而言,根据您所描述的内容,我会单独留下 lru_cache (以及直接向您的数据库查询添加额外缓存的任何想法)。这种内存缓存对于经常访问且必须一次性计算的事物、非常昂贵但产生相同结果的调用、必须调用有费用的外部 API 的情况很有帮助/ 不可靠等。如果在 ORM 前面堆积复杂性之前,您似乎一直在向用户展示相同的页面,我会缓存到表示层 - 您可能希望您的经理实际与您的模型交互调用时预期。

    跟进 12-10-16

    自从这个答案以来,我有机会使用django cachalot 并发现如果您决定要缓存数据库查询,它会非常有效。它需要很少的设置工作,并且对文档中的权衡进行了精彩的探索。

    跟进 08-05-20

    django_cachalot 目前与最新的 Django (3.1+) 不兼容,所以我仍然不推荐它,目前也不使用它。如果您需要更重的 ORM 缓存,django_cacheops 是当前可行的。

    【讨论】:

    • 我想指出,当我开始时,我目前正在从事的项目有 cachalot,而且还有许多难以重现的与数据库查询有关的错误。我们甚至将数据库提供商从自托管转移到托管,但没有解决任何问题。当我知道 cachalot 在做什么时,我立即删除了它,不仅那类 bug 消失了,我们的大多数(写得不好的)视图实际上都加速了。
    • 自从这个后续,我实际上没有再使用cachalot,因为它与新版本的Django不兼容。我使用了django-cacheops,它需要更一致的方法和配置,并且有自己的怪癖(尤其是在管理员中)。它的“魔力”比cachalot少。我不认为我可以/会再次使用cachalot,因为我从事的所有项目都试图保持在最新的稳定和安全的 Django 上。感谢您的注意,我会修改答案,因为已经有一段时间了。
    猜你喜欢
    • 2020-10-22
    • 2011-06-19
    • 1970-01-01
    • 2019-12-07
    • 2021-05-15
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多