数据库设计中多个“项集”的方法

时间:2011-08-13 07:48:18

标签: mysql database-design

我有一个数据库设计,我将图像文件名存储在名为 resource_file 的表中。

CREATE TABLE `resource_file` (
  `resource_file_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `resource_id` int(11) NOT NULL,
  `filename` varchar(200) NOT NULL,
  `extension` varchar(5) NOT NULL DEFAULT '',
  `display_order` tinyint(4) NOT NULL,
  `title` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `canonical_name` varchar(200) NOT NULL,
  PRIMARY KEY (`resource_file_id`)
) ENGINE=InnoDB AUTO_INCREMENT=592 DEFAULT CHARSET=utf8;

这些“文件”收集在另一个名为资源的表格下(类似于专辑):

CREATE TABLE `resource` (
  `resource_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `description` text NOT NULL,
  PRIMARY KEY (`resource_id`)
) ENGINE=InnoDB AUTO_INCREMENT=285 DEFAULT CHARSET=utf8;

如果我想将某种类型的“资源”(专辑)分配给特定类型的“项目”(产品,用户,项目和等),这个设计背后的逻辑很方便,例如:

CREATE TABLE `resource_relation` (
  `resource_relation_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `module_code` varchar(32) NOT NULL DEFAULT '',
  `resource_id` int(11) NOT NULL,
  `data_id` int(11) NOT NULL,
  PRIMARY KEY (`resource_relation_id`)
) ENGINE=InnoDB AUTO_INCREMENT=328 DEFAULT CHARSET=utf8;

此表格包含资源与特定类型的商品之间的关系,如:

  • 产品
  • 用户
  • &安培;等

我这样做的方法是给“module_code”一个像“product”或“user”这样的值,并将 data_id 分配给相应的unique_id,在本例中为product_id或user_id。 /> 所以在一天结束时,如果我想查询分配给id为123的产品的资源,我会查询resource_relation表:(非常简化的伪查询)

SELECT * FROM resource_relation WHERE data_id = 123 AND module_code = 'product'

这给了我资源,我可以找到相应的图像。

  • 我发现这种方法非常实用,但我不知道这个特定问题是否是正确的方法
  • 这种方法的名称是什么?
  • 这是一个有效的设计吗?

谢谢

3 个答案:

答案 0 :(得分:2)

enter image description here

这个使用超类型/子类型。请注意主键如何从超类型表传播到子类型表。

答案 1 :(得分:1)

首先回答您的第二个问题:表resource_relationan Entity-attribute-value model的实现。

所以下一个问题的答案是,这取决于。根据关系数据库理论,这是一个糟糕的设计,因为我们无法在data_idproduct_iduser_id等之间强制执行外键关系。它还会混淆数据模型,它可以更难进行影响分析。

另一方面,很多人发现EAV是一个特定问题的实用解决方案,只有一个表而不是几个。虽然,如果我们谈论实用性,EAV不能很好地扩展(至少在关系产品中,有NoSQL产品可以做不同的事情)。

从中得出,你的第一个问题的答案是正确的方法吗?是“严格,不是”。但这有关系吗?也许不是。


  

“我不明白为什么这会”不“缩放。你介意吗?   进一步解释一下? “

EAV存在两个常见问题。

第一个是小结果集(比如DATE_ID=USER_ID)和大结果集(比如DATE_ID=PRODUCT_ID)使用相同的查询,这可能会导致次优的执行计划。

第二个是向实体添加更多属性意味着查询需要返回更多行,而关系解决方案将返回相同数量的行,包含更多列。这是主要的缩放成本。这也意味着我们最终会写出可怕的查询like this one

现在,在您的具体情况下,这些问题可能都不相关。我只是解释了EAV导致问题的原因。

  

“我应该如何分配”资源“,例如,我的   产品表,“正常的方式”?“

更常见的方法是为每个关系设置不同的交集表(AKA联结表),例如USER_RESOURCES,PRODUCT_RESOURCES等。每个表将由复合主键组成,例如, (USER_ID, RESOURCE_ID),可能没什么其他的。

另一种方法是使用具有特定子类型表的通用超类型表。这是Damir has modelled的实现。超类型的正常使用caee是当我们有一堆相关实体时,它们具有一些共同的属性,行为和用法以及它们自己的不同特征。例如,PERSON和USER,CUSTOMER,SUPPLIER。

关于您的方案,我认为USER,PRODUCT和GALLERY不符合这种方法。当然,他们都是RESOURCE的消费者,但这几乎是他们的共同点。因此,尝试将它们映射到ITEM超类型是一种procrustean解决方案;获得一个通用的ITEM_RESOURCE表可能是一个很小的奖励,你将不得不跳到其他地方。

答案 2 :(得分:0)

  

我有一个数据库设计,我将图像存储在一个名为的表中   resource_file。

你没有存储图像;你正在存储文件名。文件名可能识别也可能不识别图像。您需要保持数据库和文件系统权限的同步。

您的resource_file表结构显示“图像文件名在数据库中是可识别的,但在文件系统中无法识别。”它说因为resource_file_id是主键,但除了id之外没有唯一的约束。我怀疑你的图像文件实际上在文件系统中是可识别的,并且你最好使用符合该现实的数据库约束。可能是(文件名,扩展名)的唯一约束。

资源表的想法相同。

对于resource_relation,您可能需要对(resource_id,data_id)或(resource_id,data_id,module_code)具有唯一约束。但是。 。

我会稍后再考虑一下这个问题。有点难以弄清楚你正在尝试做什么的资源调配,这通常是一个红旗。