首页 > 代码库 > 第一章: 在RDB中的树结构数据

第一章: 在RDB中的树结构数据

第一章: 在RDB中的树结构数据

在本章中,我将写一个基本的知识来理解这个问题

一  模型的作用

RBD处理树模型的作用总结为两点:

1  在RDB表中保存树的数据

2  效率的查询节点的相关节点

1  在RDB表中保存树的数据

我们可以定义的标准,该模型是否具有存储层次数据的功能

可以由保存的所有节点再现原有的层次结构

如果不能通过保存的数据再现原有的树结构,就不能说这个模型实现了树。

2  效率的查询节点的相关节点

通常,我们将数据保存到数据库中进行搜索,数据中保存了分层数据,可能会查询任何节点的关系数据(如子树、父节点、子节点,祖先节点,子孙节点等)。这是一个树模型的重要作用。

如下[A], [B], [C]等表示节点。

                [A]               |           +---+---+           |       |          [B]     [C]           |       |         +-+-+   +-+-+         |   |   |   |        [D] [E] [F] [G]                     |                   +-+-+                   |   |                  [H] [I]
当我们查询[C]的子树时,通过跟踪向下延伸的分支来获取所有的节点。
           [C]           |         +-+-+         |   |        [F] [G]             |           +-+-+           |   |          [H] [I]
跟踪向下延伸的分支是很有规律性的,因此很多人认为如果将分层数据保存在数据库中,我们将很容易地查找到任何节点的相关节点。
树形结构数据会像一下的数据集合被频繁的搜索。

节点

关系

节点集合

[B]父节点[A]
[B]子节点[D] [E]
[H]祖宗节点[A] [C] [G]
[C]子孙节点[F] [G] [H] [I]
[C]部分木[C] [F] [G] [H] [I]
有效一词在这里是非常重要的,不然也没有必要设计查询。
这里做查询时首先要得到所有节点,然后通过查询条件过滤。然而,在一个百万级数据的表中,我们获取全部节点时需要大量的执行时间和内存,每次得到所有的节点是不现实的。如果表中有大量的百万级相关联的节点,这个系统的设计在速度将很难上达到指标。
 

二  实例

通过实例,说明如何利用查询查找层次数据中的相关节点。

查找祖先节点使用网上的"breadcrumbs list"。

1  祖先节点查找的实例

        [Top Page]            |--[Products]            |     |--[Smart Phone Apps]            |     +--[Desktop Apps]            |--[News]            |     |--[2015/10]            |     |--[2015/09]            |     |--[2015/08]            |     +--[2015/07]            +--[About Us]                  |--[Corporate Philosophy]                  |--[Access]                  +--[Contact Us]
当我们查询[Corporate Philosophy]的节点,通过跟踪向上延伸在其顶端的节点如下。
Top Page > About Us > Corporate Philosophy
所有的过度的页面都会被认为是树结构,首页为根节点。当能够找到Corporate Philosophy的祖先节点就可以再现breadcrumbs list

2  子孙节点查找的实例

论坛有回复注释的功能,以此为树,当将所有注释视为节点时,所存储的数据具有层次结构。查询论坛中的评论时,我们会使用寻找子树节点。

        [2015/03/31]            |--[Let‘s Party tonight! (John)]            |     |--[I will join! (Mike)]            |     |     +--[Thanks! (John)]            |     |--[Can not join tonight. (Anne)]            |     |     +--[When OK? (John)]            |     +--[OK, but 2 hours only. (Tom)]            |           |--[Me too. (Eucen)]            |           +--[I see! (John)]            +--[I losted my smart phone. (Bill)]                  |--[When? (Diana)]                  |     +--[Yesterday. (Bill)]                  +--[Did you check GPS? (Fred)]                        +--[Yet (Bill)]
 
如上,在2015年3月31日有两个线程,当只显示Let‘s Party tonight! (John)时就需要查询评论John的所有子树。在这种情况下,由于论坛海量数据节点的纯在效率问题,不能使用查找所有节点的方法。
 

三  关系模型的问题点

再次重申下RBD处理树模型的作用。

1  在RDB表中保存树的数据

2  效率的查询节点的相关节点

很难写出一个高效的查询原因有一下几点。

1  要想搜索,首先要保存每个节点的所有祖先节点

2  节点关系数据量相对深度呈指数倍增长

3  层次的深度不取决于数据的内容

4  在数据库中对层次数据赋予索引是困难的。因为树结构具有二维扩散,但指数是一维结构

5  等等

如果从指定节点找到一组子孙节点,可以通过跟踪分支方向来确定,这是一个简单的事。然而SQL是说明性编程(declarative programming),因此不能为每个节点确定关系,比如在单独的进程中使用命令式编程。

在声明式编程,我们如何能够表达在搜索查询子树和祖先节点的关系?

世界各地的数据库工程师都在挑战这个问题,RDB中的分层数据的问题点关键就在于“如何有效的查询节点相关的任何节点”。

 

四  列的追加

为了解决存储层次树数据,工程师们已经研发了四种模型来解决这个问题。

邻接表模型(adjacency list model)

路径枚举模型(path enumeration model)

嵌套集合模型(nested set model)

关闭表模型(closure table model)

无论在哪一种模型中,无非都是在RDB中添加一些列来保存分层数据。所添加的列按照其作用可以分为两类。

1  层次结构列

2  效率搜索列

1  层次结构列

需要保存层次数据在RDB表中。也在查询中被用作为一个检索条件的列。

2  效率搜索列

第一章: 在RDB中的树结构数据