我有一个数据库设计,我将图像文件名存储在名为 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'
这给了我资源,我可以找到相应的图像。
谢谢
答案 0 :(得分:2)
这个使用超类型/子类型。请注意主键如何从超类型表传播到子类型表。
答案 1 :(得分:1)
首先回答您的第二个问题:表resource_relation
是an Entity-attribute-value model的实现。
所以下一个问题的答案是,这取决于。根据关系数据库理论,这是一个糟糕的设计,因为我们无法在data_id
和product_id
,user_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)具有唯一约束。但是。 。
我会稍后再考虑一下这个问题。有点难以弄清楚你正在尝试做什么的资源调配,这通常是一个红旗。