【问题标题】:How to maintain a recursive invariant in a MySQL database?如何在 MySQL 数据库中维护递归不变量?
【发布时间】:2008-08-21 16:20:12
【问题描述】:

我有一个在 MySQL 数据库中编码为边的树:

CREATE TABLE items (
    num INT,
    tot INT,
    PRIMARY KEY (num)
    );
CREATE TABLE tree (
    orig INT,
    term INT
    FOREIGN KEY (orig,term) REFERENCES items (num,num)
    )

对于树中的每一片叶子,items.tot 是由某人设置的。对于内部节点,items.tot 必须是其子节点的总和。重复运行以下查询将产生所需的结果。

UPDATE items SET tot = (
    SELECT SUM(b.tot) FROM
        tree JOIN items AS b
        ON tree.term = b.num 
        WHERE tree.orig=items.num)
    WHERE EXISTS 
        (SELECT * FROM tree WHERE orig=items.num)

(注意这实际上是行不通的,但这不是重点)

假设数据库存在并且已经满足不变量。

问题是:

在保持此要求的同时更新数据库的最实用方法是什么?更新可能会移动节点或改变叶节点上tot 的值。可以假设叶子节点将保持为叶子节点,内部节点将保持为内部节点,整个事物将保持为一棵适当的树。

我的一些想法:

  • 完全失效,任何更新后,重新计算一切(嗯...否)
  • 在 items 表上设置触发器以更新任何已更新行的父级
    • 这将是递归的(更新触发更新、触发更新……)
    • 不起作用,MySQL 无法更新启动触发器的表
  • 设置触发器以安排更新任何已更新行的父行
    • 这将是迭代的(从计划中获取一个项目,处理它以安排更多项目)
    • 是什么开始的?相信客户端代码会做对吗?
    • 一个优点是,如果更新排序正确,则需要计算机计算的总和更少。但这种排序本身就是复杂的。

理想的解决方案可以推广到其他“聚合不变量”

FWIW 我知道这“有点过火”,但我这样做是为了好玩(有趣:动词,通过这样做找到不可能的事情。:-)

【问题讨论】:

    标签: mysql algorithm data-structures invariants


    【解决方案1】:

    您遇到的问题很明确,是 SQL 中的递归。您需要获取叶子的父级...的父级并更新它的总数(减去旧的并添加新的,或重新计算)。您需要某种形式的标识符来查看树的结构,并获取所有节点子节点和要更新的叶子的父节点/路径列表。

    这种方法增加了固定空间(2 列到您的表中——但您只需要一个表,否则您可以稍后进行连接)。不久前我玩弄了一个结构,它使用了使用“左”和“右”列(显然不是那些名称)的分层格式,分别由前序遍历和后序遍历计算——别担心这些不需要每次都重新计算。

    如果您不喜欢这种方法作为答案,我会让您看一下 using this method in mysql 页面,而不是继续讨论。但是,如果您喜欢它,请发布/编辑,我会花一些时间进行澄清。

    【讨论】:

    • 一个有趣的方法。我不喜欢它的地方是它使用了N*Log(N) 空间之类的东西。此外,我还有一些需要主要模组的版本控制限制。 -- 遗憾的是,作者从未深入探讨如何更新聚合值。我可以想到一些方法,但它们将取决于该实现。 ——我得再考虑一下。 (从 [非常旧的] 答案移动。)
    • 我更新了提到格式的 mysql 文档的链接。
    【解决方案2】:

    我不确定我是否正确理解了您的问题,但这可能有效My take on trees in SQL

    链接的帖子描述了在数据库中存储树的方法——在这种情况下是 PostgreSQL——但该方法足够清晰,因此可以轻松地用于任何数据库。

    使用这种方法,您可以使用大约 N 个简单的 SELECTs 查询轻松更新所有依赖于修改节点 K 的节点,其中 N 是距离K 来自根节点。

    我希望你的树不是很深:)。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 2018-09-09
      • 1970-01-01
      • 2014-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多