如何使用MySQL存储此分层数据?

时间:2013-08-14 05:14:14

标签: mysql tree

我目前正在设计一个将被许多企业使用的网络应用程序。但是,我无法确定如何存储数据。此树中演示了数据的一般结构:http://i.imgur.com/lpYwqya.png

因此会有一个列出每个客户端的表。每个客户都有自己的用户和项目。每个项目都有两个孩子:用户和任务。用户指的是允许访问该项目的客户端下注册的用户(将存储该用户的id,以及他们的权限[读/写])对于树的每个级别,我需要存储数据。例如,任务具有以下字段(WBS,名称,开始日期,完成日期,持续时间,工作,成本,固定成本,供应商......)

我很难决定如何最好地构建数据。请注意,数据将始终从树的顶部(父母到孩子)访问,我永远不必跨越孩子或备份树。以下是我提出的两个解决方案:

解决方案1 ​​:拥有无限数量的表格。每次创建客户端时,还会创建两个表:1_projects和1_users(其中1是第一个表中客户端的id)。创建项目时,将创建表1_1_tasks,依此类推。因此,id为5,任务ID为3895,项目ID为19,客户端ID为57658的风险计划表为:57658_19_3895_5_plans。

解决方案2 :拥有9个表:客户,用户,项目,project_users,任务,风险,risk_updates,计划,plan_updates。在risk表中,除了每个风险与之关联的字段外,它还具有以下内容:client_id,project_id,task_id。因此,例如,如果我想要返回客户端对特定任务的所有风险,我会在整个树中搜索client_id =#,project_id =#,task_id =#的风险。当然,这些字段将形成风险表的复合/复合键。因此,风险表将存储每个项目和每个客户的每项任务的风险。最后一张表plan_updates显然会非常庞大​​。

我认为解决方案1很强大,因为它允许我轻松地向下导航树,因为不属于同一父节点的节点不存储在同一个表中。但是,这个解决方案也非常糟糕,因为会有大量的表,所以以后对数据库的任何修改都会非常困难。

解决方案2很强大,因为所有风险都集中在一个表中。但是,我想知道在搜索say_updates表时是否效率非常低,因为我必须搜索整个表(对于与所有父元素的id匹配的字段来说将是巨大的)。

为了全面考虑这一点,我预计会有以下几点:

用户:每位客户1-20。通常小于5。

项目:每个客户1-100。大多数将少于20个。

任务:每个项目100-10,000。

风险:每项任务0-10。但是,只有大约30%的任务会有风险,其中大部分只会有1-4个风险。

风险更新:每风险1-10个。

计划:每个风险1-5个。

计划更新:每个计划1-10个。

如果有人能说明如何最好地解决这个问题,那将非常有帮助。

2 个答案:

答案 0 :(得分:1)

第二种解决方案对我来说似乎更合理。第一个解决方案中最大的缺陷是整个结构的可管理性差。您很快就会得到大量的表格,如果结构发生变化(需要添加额外的字段或额外的约束),您将遇到麻烦。

另一方面,您对复合键的担忧并不严重。

例如,可以将任务分配给单个项目。他们也没有必要直接向客户提供参考。另一方面,您很可能会在某个时候引入另一个直接连接用户和任务的n-n链接表,以便定义执行该特定任务的人员。

因此,如果要列出任务的所有风险,首先必须找到手头的任务,然后使用单个密钥(任务ID)扫描风险表。无论您有一个还是多个表,都保持不变。

我强烈建议您选择#2,并确保识别所有相关的主键和索引(以及适用的唯一列)。这将使数据库快速有效。

修改

正如@MSW所提到的,关于这个主题还有很多话要说。关于数据库设计(包括常态,原子性等原则)的文献无穷无尽,涵盖了主题。

另一个解释解决方案#1质量差的问题还在于,在以后的某个时间点,您将无法轻松地在各个项目中进行分析,因为它们都将处于较大的状态不同表格的数量。

答案 1 :(得分:0)

远离您的解决方案#1。更好地坚持你的解决方案#2,但有一些变化。

您的Risks表不需要这些键:client_id,project_id,task_id。您只需要task_id(作为外键),因为您的Tasks表已与​​您的Projects关联。与计划,风险更新等相同。就像你提到的那样,你总是从上到下访问它(将表从项目连接到任务再到风险等等)。