在关系数据库中存储分层数据的选项有哪些?

好的概述

一般来说,您要在快速读取时间(例如,嵌套集)或快速写入时间(邻接列表)之间做出决定。通常,您最终会得到以下最适合您需要的选项组合。以下内容提供了一些深入阅读:

  • 还有一个嵌套间隔与邻接列表比较:我找到的邻接列表、物化路径、嵌套集和嵌套间隔的最佳比较
  • 分层数据模型:幻灯片,很好地解释了权衡和示例用法
  • 在MySQL中表示层次结构:特别是嵌套集的非常好的概述
  • RDBMS中的分层数据:我见过的最全面、组织最完善的链接集,但在解释方面不多

选项

我知道的和一般特征:

  1. 邻接列表:
  • 列:ID,ParentID
  • 易于实现
  • 廉价节点移动、插入和删除
  • 查找级别、祖先和;后代、道路
  • 通过支持N+1的数据库中的公共表表达式避免N+1
  1. 嵌套集(又称修改的前序树遍历)
  • 列:左、右
  • 廉价的祖先、后代
  • 非常昂贵的O(n/2)由于易失性编码而移动、插入和删除
  1. 桥接表(又称闭合表/带触发器)
  • 使用单独的联接表:祖先、后代、深度(可选)
  • 廉价的祖先和后代
  • 写入插入、更新和删除的成本O(日志n)(子树大小)
  • 规范化编码:适用于RDBMS统计&联接中的查询计划器
  • 每个节点需要多行
  1. 沿袭列(又称物化路径、路径枚举)
  • 列:血统(例如/父/子/孙/等)
  • 通过前缀查询的廉价后代(例如左(沿袭,#)='/enumerated/path'
  • 写入插入、更新和删除的成本O(日志n)(子树大小)
  • 非关系:依赖于数组数据类型或序列化字符串格式
  1. 嵌套区间
  • 与嵌套集类似,但使用实数/浮点数/十进制数,因此编码不会易变(便宜的移动/插入/删除)
  • 存在实/浮/十进制表示/精度问题
  • 矩阵编码变体为“添加祖先编码(具体化路径)”;免费;,但是线性代数又增加了一些技巧
  1. 平板
  • 一种修改的邻接列表,在每条记录中添加一个级别和等级(如排序)列
  • 重复/分页的成本很低
  • 昂贵的移动和删除
  • 好用:线程化讨论-论坛/博客评论
  1. 多个沿袭列
  • 列:每个沿袭级别对应一列,表示到根的所有父级,从项目级别向下的级别设置为NULL
  • 廉价的祖先、后代、等级
  • 廉价的插入、删除、移动叶子
  • 昂贵的内部节点插入、删除和移动
  • 硬限制层次结构的深度

特定于数据库的注释

MySQL

  • 将会话变量用于邻接列表

甲骨文

  • 使用“连接方式”遍历邻接列表

PostgreSQL

  • 物化路径的ltree数据类型

SQL Server

  • 概述
  • 2008提供的HierarchyId数据类型似乎有助于采用沿袭列方法并扩展可表示的深度

我最喜欢的答案是这个帖子的第一句话。使用邻接列表维护层次结构,并使用嵌套集查询层次结构

到目前为止的问题是,从邻接列表到嵌套集的转换方法非常慢,因为大多数人使用称为“推堆栈”的极端RBAR方法进行转换,一直被认为是一种昂贵的方法,可以通过邻接列表和嵌套集的出色性能实现维护的简单性。因此,大多数人最终不得不满足于其中一个,尤其是当节点数超过(比如)糟糕的100000个左右时。使用推栈方法可以花一整天的时间来完成MLME将被认为是百万字节层次结构的转换。

我想我会给Celko一点竞争的机会,想出一种方法,以似乎不可能的速度将邻接列表转换成嵌套集。下面是我的i5笔记本电脑上推堆栈方法的性能

1000个节点的持续时间=00:00:00:870
10000个节点的持续时间=00:01:01:783(比10个节点慢70倍)
100000个节点的持续时间=00:49:59:730(比100个节点慢3446倍)
1000000个节点的持续时间=’甚至没有尝试此操作’

这是新方法的持续时间(括号中有push-stack方法)

1000个节点的持续时间=00:00:00:053(与00:00:00:870相比)
10000个节点的持续时间=00:00:00:323(与00:01:01:783相比)
100000个节点的持续时间=00:00:03:867(与00:49:59:730相比)
1000000个节点的持续时间=00:00:54:283(相比之下,大约2天!!!)

是的,没错。在不到一分钟的时间内转换了100万个节点,在不到4秒内转换了100000个节点

您可以阅读有关新方法的信息,并从以下URL获取代码副本。
http://www.sqlservercentral.com/articles/Hierarchy/94040/

我还使用类似的方法开发了一个“预聚合”层次结构。传销商和制作物料清单的人对本文特别感兴趣。
http://www.sqlservercentral.com/articles/T-SQL/94570/

如果你确实来看看这两篇文章,请跳进“加入讨论”链接,让我知道你的想法

发表评论