为什么 Django 返回过时的缓存数据?

2023-11-22

我有两个 Django 模型,如下所示,MyModel1 & MyModel2:

class MyModel1(CachingMixin, MPTTModel):
    name = models.CharField(null=False, blank=False, max_length=255)
    objects = CachingManager()

    def __str__(self):
        return "; ".join(["ID: %s" % self.pk, "name: %s" % self.name, ] )

class MyModel2(CachingMixin, models.Model):
    name = models.CharField(null=False, blank=False, max_length=255)
    model1 = models.ManyToManyField(MyModel1, related_name="MyModel2_MyModel1")
    objects = CachingManager()

    def __str__(self):
        return "; ".join(["ID: %s" % self.pk, "name: %s" % self.name, ] )

MyModel2有一个 ManyToMany 字段MyModel1有权model1

现在看看当我向此 ManyToMany 字段添加新条目时会发生什么。根据 Django 的说法,它没有任何效果:

>>> m1 = MyModel1.objects.all()[0]
>>> m2 = MyModel2.objects.all()[0]
>>> m2.model1.all()
[]
>>> m2.model1.add(m1)
>>> m2.model1.all()
[]

为什么?这似乎肯定是一个缓存问题,因为我看到数据库表 myapp_mymodel2_mymodel1 中有一个新条目用于此链接m2 & m1。我应该如何修复它?


django-cache-machine 真的需要吗?

MyModel1.objects.all()[0]

大致翻译为

SELECT * FROM app_mymodel LIMIT 1

像这样的查询总是很快。无论是从缓存还是从数据库获取,速度都没有显着差异。

当您使用缓存管理器时,您实际上会在这里增加一些开销,这可能会使速度变慢一些。大多数时候,这种努力都会被浪费,因为可能没有缓存命中,如下一节所述。

django-cache-machine 是如何工作的

每当您运行查询时,CachingQuerySet将尝试找到该查询 在缓存中。查询的关键字是{prefix}:{sql}。如果它在那里,我们 返回缓存的结果集,大家都很高兴。如果查询不是 在缓存中,执行运行数据库查询的正常代码路径。 当结果集中的对象被迭代时,它们被添加到 迭代完成后将被缓存的列表。

source: https://cache-machine.readthedocs.io/en/latest/

因此,在您的问题中执行的两个查询相同的情况下,如果缓存尚未失效,缓存管理器将从内存缓存中获取第二个结果集。

同一链接解释了缓存键如何失效。

为了支持简单的缓存失效,我们使用“刷新列表”来标记 对象所属的缓存查询。这样,所有查询都在 当该对象发生更改时,找到的对象将失效。冲洗 列表将对象键映射到查询键列表。

当对象被保存或删除时,其刷新列表中的所有查询键 将被删除。此外,其外键的刷新列表 关系将被清除。为了避免陈旧的外键关系,任何 当对象的外键被刷新时,缓存的对象将被刷新 指向无效。

很明显,保存或删除对象将导致缓存中的许多对象失效。因此,您可以通过使用缓存管理器来减慢这些操作的速度。另外值得注意的是,失效文档根本没有提及多对多字段。有一个开放问题为此,从您对该问题的评论来看,很明显您也发现了它。

Solution

卡盘缓存机。缓存所有查询几乎不值得。它会导致各种难以发现的错误和问题。最好的方法是优化您的表并微调您的查询。如果您发现某个特定查询太慢,请手动缓存它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Django 返回过时的缓存数据? 的相关文章

随机推荐

  • jQuery data() 如何打破循环引用

    我读过一篇为什么它更好 and 它是如何实施的 但我真正不明白的是它如何打破循环引用 它如何打破参考圆 div1 data item div2 div2 data item div1 例如 上面的div互相指向 如何防止 我有一种预感 但我
  • 在不裁剪的情况下缩放 SDL Surface 的正确方法?

    缩放 SDL Surface 的正确方法是什么 我在网上找到了一种解释 但它需要逐像素地重新绘制表面 似乎应该有某种方法可以通过 SDL 本地执行此操作 而不是像那样重新绘制图像 我在 SDL 文档中找不到任何涉及此内容的内容 我可以通过修
  • 从 sbt shell 中设置环境变量

    我希望能够在交互式 sbt shell 中设置环境变量 但我似乎找不到方法来做到这一点 我查看了官方 sbt 文档以及 stackoverflow 但没有成功 我想明确的是我不想要必须在中设置此环境变量build sbt文件 而是能够在交互
  • android从布局xml动态添加元素

    如何从此布局 xml 中获取元素 myButton
  • 如何获取 RawInput HID 设备的人类可读名称?

    我正在将应用程序从 DirectInput 切换到 RawInput 以进行游戏手柄处理 并且我想为每个游戏手柄提供人类可读的描述 理想的情况是显示在设备管理器中的设备文本 但 USB 产品描述也可以 任何方法都应该在没有管理员许可的情况下
  • 谷歌地图 setMap 不是一个函数

    我正在处理我的谷歌地图页面在 Firebug 中显示错误的问题 当我在经销商地图中搜索时 将触发 clearLocations 函数 但出现了这个错误 markers i setMap 不是一个函数 有谁知道如何解决这个问题 我在几个论坛和
  • 更改列名而不重新创建 MySQL 表

    有没有办法在不进行重大更改的情况下重命名 InnoDB 表上的列 桌子相当大 我想避免重大停机 重命名列 使用ALTER TABLE CHANGE COLUMN 不幸的是需要 MySQL 运行全表复制 查看pt 在线架构更改 这有助于您对表
  • Netbeans 更新失败

    我的互联网连接没有问题 但是当我尝试更新 netbeans 插件或 IDE 本身时 每次都会出现此屏幕 即使重新安装操作系统也无法解决此问题 一次又一次地遇到同样的错误 我该如何修复它 在 Netbeans 中 Go to Tools gt
  • 使用 jQuery 更改图像地图坐标值

    我有一个非常复杂的图像映射 我想将其缩小一半 为此 需要将所有坐标值除以 2 由于有数千个坐标值 我想我可以使用 jQuery 遍历 DOM 来查找坐标值 然后将它们除以 2 当涉及到 JavaScript 和 jQuery 时 我非常业余
  • 为什么“复制到输出目录”选择的用语在不同位置之间会发生变化?

    VS NET 中的解决方案资源管理器中的配置值措辞与 VS NET 中的预计值之间存在不一致 csproj文件 在Solution Explorer a config或依赖文件中会有多个选项Copy To Output Directory影
  • Laravel 5.6:创建图像缩略图

    在我的旧 PHP 应用程序中 我曾经运行如下函数来创建 jpeg 图像缩略图 function imageThumbanail image src imagecreatefromjpeg http examplesite com image
  • Luigi - 覆盖任务需要/输入

    我正在使用 luigi 执行一系列任务 如下所示 class Task1 luigi Task stuff luigi Parameter def output self return luigi LocalTarget test json
  • Rust 的句法语法是上下文无关的还是上下文相关的?

    几乎没有任何编程语言的句法语法是规则的 因为它们允许任意深度嵌套的括号 Rust 也这样做 let x 但 Rust 的句法语法至少是上下文无关的吗 如果不是 什么元素使语法与上下文相关 或者语法是否可以递归枚举 例如C 的句法语法 Rel
  • 为什么我需要文档类型? (它有什么作用)[重复]

    这个问题在这里已经有答案了 可能的重复 HTML DOCTYPE 的功能是什么 我最近在这里问了一个问题 解决方案很简单 您需要向页面添加文档类型 这应该可以解决您的问题 现在 我的页面在没有文档类型的每个浏览器中都可以正常工作 IE 除外
  • jQuery 多文档就绪队列顺序

    我知道 jQuery 中对 function 的调用是按照定义的顺序执行的 但我想知道您是否可以控制队列的顺序 例如 是否可以在 Hello World 1 之前调用 Hello World 2 function alert Hello W
  • 使用 SharpSvn 检索日期范围内的日志条目

    我在用着SharpSvn通过 C 代码与我的 svn 存储库交互 我使用此代码来检索 svn 日志条目 Collection
  • 如何设置输入超时

    如果你等了 4 秒 它会说 你没时间了 这很好 但是 为了保持循环继续 您必须按enter键继续 我希望当它在下面打印 你没时间了 而不是仅仅键入时 它会显示一个输入语句 例如 键入 攻击 以继续 并且循环将从原来的位置继续 from th
  • SQLAlchemy 根据 JSONB 中的嵌套键进行过滤

    我有一个 JSONB 字段 有时有嵌套键 例子 nested field another URL foo a simple text text first metadata plain string another metadata foo
  • 通过 Uri 将参数传递到 WPF 页面

    在导航样式 WPF 应用程序 NavigationWindow 而不是 XBAP 的上下文中 超链接的 NavigateUri 是否可以包含额外的参数 例如路径数据或查询字符串 例如 有什么方法可以将我的 NavigateUri 设置为 P
  • 为什么 Django 返回过时的缓存数据?

    我有两个 Django 模型 如下所示 MyModel1 MyModel2 class MyModel1 CachingMixin MPTTModel name models CharField null False blank False