4

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

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

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

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

4

2 回答 2

2

当您需要对树进行频繁更新时,嵌套集设计绝对是困难的。您最终不得不重新编号树的大部分。

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

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

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


回复您的评论:

Adjacency List 很简单,冗余最少,并且支持 FK 关系,而 Nested Sets 则不支持。如果您使用递归查询,邻接表支持查询任意深度的整个树。但是 MySQL 不支持递归查询。

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

于 2013-01-01T21:52:24.933 回答
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_datestart_datestop_date字段来扩展以提供历史层次结构roster

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

于 2013-01-01T21:50:37.777 回答