树形结构的存储是一种非常典型的需求,例如菜单、省市区、栏目等等。
1. 关系型数据库
实现方式1
id、name、pid
将树形结构的每个节点作为一行存储,每个节点保存父节点的指针(pid)。优点是简单易懂,插入修改比较简单。缺点是若要获取某个节点的所有子节点,将是一件非常恶心的事情。
实现方式2
id、name、pid、left、right
在方式1中增加left和right,相当于btree的左右分支,分别存储左右分支节点的最大值和最小值。优点是查询一个节点的子节点容易,仅需做范围查询查询即可。缺点是由于树形结构存储在里面,增加或修改已存在的节点将可能产生连锁反应,操作复杂。
2. 文档型数据库
实现方式1
{
name:'A',
children:[
{name:'B', children:[
{name:'D'}
]},
{name:'C'}
]
}
将整个树结构存成一个文档,文档结构即树形结构,简明易懂。缺点是文档越来越大,对所有节点的修改都集中在此文档中,并发操作受限。
实现方式2
{_id:"A", children:["B", "C"]}
{_id:"B", children:["D"]}
{_id:"C"}
{_id:"D"}
将每个节点的子节点保存起来,优点是结构简单查询子节点方便,缺点是查询父节点会表麻烦。
实现方式3
{
leaf:"A",children:[
{leaf:"B", children:[
{leaf:"D"}
]},
{leaf:"C"}
]
}
{_id:"A", ...}
{_id:"B", ...}
{_id:"C",...}
充分利用文档型存储 schema-less的优点,受限存储一个大的树形文档,再将每个节点的其他信息单独存储。优点是操作简单,结构上的操作可直接操作树形文档,数据上的操作仅需操作单条数据。缺点,对所有节点的修改都集中在此文档中,并发操作受限。