2010-12-13 200 views
3

可能重复的树木:
What is the most efficient/elegant way to parse a flat table into a tree?数据库结构和查询层次数据和数据

这我发现相当棘手的,并希望对此事的一些看法。 我想存储分层数据(树状)与未知数量的层次和分支。我希望能够随时添加新的和删除任何内容。

由于庞大的用户群,我需要能够从层次结构中的任何节点一次查询所有子级ID的查询。

让我们假设一个网站的家庭社交化和更新他们的地位,如Facebook在任何时候你可以查看家庭成员“墙”,其中还包括所有最近的状态更新下面的人他们按照时间顺序排列在层次结构中。

很显然,一旦你拥有了这个家庭成员身份证的数组,这个家庭成员节点的子节点,获取帖子在循环中很容易。

让我们的例子简单的表结构:

id | parentId | name 
________________________ 

1 | NULL | John 
2 |  1  | Peter 
3 |  1  | Bob 
4 |  3  | Emma 
5 |  2  | Sam 
6 |  4  | Gill 

等....你的想法。

我需要能够做到以上这样的东西,除非你认为结构需要适应。我已阅读mySql nested set model。 这看起来很复杂,如果有些东西不能正确更新并且会把所有东西搞砸,这可能是不可靠的。

我习惯于使用php和mysql,但一直在读cassandra和节俭。不知道这是否会更容易?

+2

我知道它看起来很费劲,但嵌套集模型真的是你想要的。它很难解释/描述这一点,而不是实现它,并且生成的SQL比蚂蚁父子指针解决方案更简单,性能更好 – 2010-12-14 01:34:04

回答

1

已经有很好的方法比您提出的解决方案更简单。

下面是一些解释如何做到这一点的链接(我们自己使用这个和你描述的很相似的问题,它工作的很好)。

这使得插入/更新更加复杂,但选择所述树结构的部分远更快(只有一个查询)。它允许在一个查询中查找任何给定节点的所有子节点,并用一个查询查找给定节点的所有祖先。

+0

嗨El Yobo,我意识到这种技术,我在我的帖子。谢谢你的头,虽然和答案!如果你考虑一下,实际上只有一个查询也是使用我提出的方法。因为我需要的是一系列的孩子ID,所以我可以从其他表中找到相关的帖子信息。我不是吗?我想获得家庭成员的名字也是一个查询......嗯......选择......能够添加数据和删除对于我的应用程序非常重要,因为它需要能够处理大量数据每个层次结构,我不想冒“腐败”的风险 – 2010-12-14 23:32:53

+0

进一步研究嵌套方法后,它需要一个额外的SQL查询来检索根节点的rgt和lft值。所以它正在分裂头发,就像我提出的方法一样,没有额外的步骤。此外,我会希望将rgt和lft的值从同一个表中的不同家族树开始,这会增加我认为由于附加的条件语句导致的进一步复杂性?这将是有点不守规矩,有超过10,000个节点。 – 2010-12-14 23:53:33

+0

啊,对不起,我没有认出“嵌套模型”这个名字:)虽然它确实不是很费劲,第一次设置它的一点点工作,那就很好。上面的方法对我来说似乎要复杂得多。 – 2010-12-14 23:58:41

0

所以我想我已经想出了一个想法。

我反对嵌套集模型的原因是因为它似乎仍然不是最好的方法,也不会是理想的性能解决方案。

我将介绍一个我一直在考虑的建议解决方案。 这个概念意味着创建一个hierarchal map表来跟踪每个家庭成员/节点之间的所有关系。

它的工作方式是:

使用该映射表结构:

id | fMemberId | parentid 
===================================== 
1 |  3  |  2 
2 |  4  |  3 
3 |  4  |  2 

1)作为一个新的家庭成员作为父母的孩子,我们会采取建立父母ID并在我们的家庭成员表中创建一个新行,并设置父级ID以供未来额外的使用和功能使用。

2)在创建该行时,我们将创建新行,并为新家族成员创建具有所有父ID的新行。

这样做的一种快速方法是从新家庭成员中获取父ID,然后对map表执行查询,以查找家族成员ID与新家庭成员父ID相同的所有行然后将数组存储在随后的父ID中,并在map表中与新的家庭成员ID一起存储。 这则仅需要一个SQL查询抢占了所有父ID的添加他们,而不是基于节点的数量大量查询

当我们观察一个家庭成员,这意味着饲料的职位,我们将能够查询数据库中的map表中的行,以获取当前系列成员的所有子代码,然后在其他表中查找发布数据。

主要的折衷是这类系统所需的潜在存储量。 但是我相信阅读速度会更快,因为没有条件SQL语句,并且也可能以这种方式快速写入数据库。

我们可以通过使用InnoDB的集群ID分配一个初始的家族ID索引并根据家族ID创建一个带有“下一个家庭成员ID”的新表来克服这个问题。

另外可靠性,如果一行没有被写入,就很容易添加它。它可以防止为了创建成员而不断地编辑行。

你对此有何看法?

到目前为止,这在我看来似乎是一个好方法。花了很多心思去到这里。我也相信它可能会随着时间的推移而得到改进,并且能够存储每个成员的id数组而不是所有的成员。仍然试图解决这个问题!