mysql层次结构存储与大树

时间:2013-01-01 21:12:06

标签: mysql database hierarchy hierarchical-data

我不知道如何在我的innoDB表中存储我的分层数据。

我已经阅读了很多关于在每一行中存储parent_id的方法的缺点。但现在问题是,我有一个非常大的数据库(约5000万行)。层次结构大多不是很深(3-6级)。

许多网站建议将“嵌套集模型”作为parent-id-stored-method的更好替代方案。但是网站的用户总是会进行更改(UPDATEINSERT等),并且由于我的表的大小,这将花费太多时间(因为“嵌套”中的更改设置模型“性能非常低。”

所以我的问题是:如何使用许多update / insert命令有效存储大型分层数据? (同样阻止整个表格不是一个选项[ - > innoDB-table])

2 个答案:

答案 0 :(得分:2)

当您需要频繁更新树时,嵌套集设计肯定很难。你最终不得不重新编号树的大部分。

减轻这种情况的一个建议是使用浮点数而不是整数。如果在树中插入新节点,则在新节点的父节点的嵌套集编号之间找到一些FLOAT编号相对容易。您最终可能会达到浮点数精度的极限,但由于您的树不是很深,不会长时间发生。

我写的另一种技术我称之为关闭表。这种存储层次结构的方法使得在大树中插入/更新/删除节点更加容易,而无需更新大量树。您仍然可以在单个非递归SQL查询中查询整个树或任何子树。

要了解有关闭包表的更多信息,请参阅:


重新评论:

邻接列表很简单,冗余最少,并且它支持FK关系,而嵌套集则不支持。如果使用recursive queries,Adjacency List支持查询任意深度的整个树。但MySQL不支持递归查询。

如果您只需要查询直接的父子关系(即一个深度级别),或者只查询固定深度的树,那么邻接列表就可以了。

答案 1 :(得分:1)

对于分层数据,我喜欢将层次结构分开。例如,如果我们处理员工层级,我通常会这样做 -

create table employee (
    id serial primary key,
    name varchar(50));

create table roster (
    id serial primary key,
    employee_id int references employee (id),
    supervisor_id int references employee (id));

可以通过向row_date表添加start_datestop_dateroster字段来扩展此历史层次结构。

请确保在适用的情况下应用unique个约束和触发器来强制执行业务规则。