代码之家  ›  专栏  ›  技术社区  ›  Dave Aaron Smith

无环有向图上祖先的高效数据库查询

  •  8
  • Dave Aaron Smith  · 技术社区  · 14 年前

    假设我有一个非循环有向图,比如一个家庭“树”(不是真正的树,因为一个孩子有两个父母)。我想把这个图的一个表示放在 关系 数据库,以便快速计算节点的所有祖先和节点的所有后代。你如何表示这个图形?如何查询所有后代?如何插入和删除节点和关系?你对这些数据做了什么假设?

    最好的解决方案将有最好的大O的数目 select/insert/delete 运行语句来查询祖先和子代,在总运行时按最佳大O断开连接,按空间要求断开连接。

    我的同事向我提出了这个问题。我有一个解决方案,但它的指数大小在最坏的情况下,所以我想看看其他人会如何解决它。

    编辑

    阐明了关系数据库。如果使用带有内置可传递闭包的图形数据库,这个问题就很简单(而且很无聊)。

    5 回复  |  直到 13 年前
        1
  •  8
  •   Wrikken    14 年前

    如果 selects &燃气轮机; manipulations Closure -表格法。是的,路径表中的路径爆炸,但它确实可以快速交付结果(与邻接模型相反),并将更新限制在相关部分(与嵌套集的50%更新相反)。

    Bill Karwin在网上做了一些很好的演示,介绍了不同型号的优缺点,请参阅 http://www.slideshare.net/billkarwin/models-for-hierarchical-data (幻灯片48是概述)。

        2
  •  4
  •   Tegiri Nenashi    14 年前

    对于SQL数据库中的DAG,似乎只有两种解决方案:

    1. 递归WITH子句。

    2. Transitive closure

        3
  •  2
  •   nawroth    14 年前

    RDBMS:不存在不是专门用来处理这种数据的。显而易见的选择是使用 graph database 相反,不需要将图形转换为不同的表示形式,您可以一直使用图形API。Marko Rodriguez的一个很好的演示文稿解释了在处理图遍历时底层数据模型的影响,请参阅 The Graph Traversal Programming Pattern 如果你想深入研究的话。

    我写了一个简单的例子 handling DAGs with the Neo4j graph database 不久前这可能对你有用。

        4
  •  2
  •   Erwin Smout    14 年前

    • 变量节点关系{节点:sometype}密钥{节点};
    • 可变边关系{parentNode:sometype子节点:sometype}键{parentNode childNode};

    “如何查询所有后代?”

    t关闭(边),其中parentNode=somevalue;

    “如何插入和删除节点和关系?”

    • 插入到边关系{TUPLE{parentNode somevalue chlidNode somevalue};
    • 删除删除条件的边;

    “你对这些数据做了什么假设?”

    有什么样的假设?您已经通过说“有向无环图”来指定了要指定的所有内容。

        5
  •  0
  •   Loïc Février    14 年前

    在关系数据库中,我将为每个节点存储:

    • 父亲
    • 祖先

      • O(logn)(找到节点就完成了)
    • 所有后代:
      • O(1)代表父亲+祖先
      • 更新父的childs O(|父的childs |)
    • :
      • O(1)更新父
      • O(logn)查找新老父亲
      • 更新父的childs两次O(|父的childs |)
      • 更新所有子体的祖先(简单替换):O(|子体|*|深度最大树|)(深度最大:替换并创建最大长度的大字符串(深度最大))

    • 树的深度
    • 孩子的数量?(平均值,最大值…)

    仅用于选择,高效,但难以更新。

    在实践中:在公羊大小的树上工作(例如memchaed,把所有的东西都放在公羊里),如果不可能的话,买更多的公羊,把你的树“cur”放在更小的树上。

    不管怎样,所有的子代都会花费很多,使用子树,您可以拥有最大深度D的子代,而不必拥有所有的子代。

    您可以从一个子树“跳”到另一个子树:请求越多,请求越快,移动节点的速度就越快(只需要更新一个子树)。

    推荐文章