2013-05-17 22 views
2

我有一张名为汽车的表,但每辆汽车都有数百个属性,并且它们随着时间的推移而不断增加(马力,扭矩,a/c,电动车窗等等)。我的表格有每个属性作为一列。当我拥有数千行和数百列时,这是正确的方法吗?另外,我将每个属性设置为一个列,以便于高级搜索/过滤。如何在需要太多列时设计数据库?

使用的MySQL数据库

感谢

+1

什么关于使用NoSQL的DB,就像MongoDB一样。它将允许您的模式轻松更改(添加新属性)。 – danieln

回答

4

这是一个有趣的问题恕我直言,答案可能取决于您的具体数据模型和实施。在这种情况下最重要的因素是数据密度

平均每行有多少实际填满?

  • 如果你的大多数领域都始终存在,那么数据范围分区可能是要走的路。
  • 如果你的大多数领域都是空的,那么状结构(如@JayC建议)可能更有吸引力。

让我们用你所提到的情况,并做一些模拟。

对于第一种情况,作用域分区,其思想是根据作用域或用途实现分区。作为按使用情况进行分区的示例,假设大多数检索的字段是“模型”,“年”,“制造商”和“颜色”。这些字段可以组成您的主[CAR]表,该ID字段的所有者将专门识别车辆。 现在我们假设发动机,马力,扭矩和气缸也会不时用于搜索,但不是那么频繁。这些可能存在于辅助表[CAR_INFO_1]上,该辅助表通过存在CAR_ID字段(外键)绑定到第一个表。继续创建你需要的分区。

优点:更简单的查询。如果您执行联合查询(例如在VIEW中),则可以合并有关车辆的所有信息。

下行:维护。每一个新的领域,必须在模型本身来实现,需要更新的数据模型来找到您所需要的领域实际上存储(或摘要视图中。)

格式是更优雅,但需要更多的数据库引擎。查看@ JayC's和@Nitzan Shaked的答案以获取详细信息。

优点:100%的数据密度。你永远不会有空的数据值。另外维护 - 通过将其作为一行添加到元数据标识符表中来创建新属性。数据结构也不太复杂。

缺点:复杂的查询,以及更复杂的执行计划。假设您需要所有2010年制造的蓝色福特汽车。这将是对第一种情况很简单:

SELECT * FROM CAR WHERE Model='Ford' AND Year='2010' AND Color='Blue' 

现在的元数据结构化模型相同的查询:

假设这两个表的存在,

CAR_METADATA_TYPE 
ID DESC 
1 'Model' 
2 'Year' 
3 'Color' 

CAR_METADATA [CAR_ID], [METADATA_TYPE_ID], [VALUE] 

查询本身会喜欢这样的:

SELECT * FROM CAR, CAR_METADATA [MP1], CAR_METADATA [MP2], CAR_METADATA [MP3] 
WHERE MP1.CAR_ID = CAR.ID AND MP1.METADATA_TYPE_ID = 1 AND MP1.Value='Ford' 
AND MP2.CAR_ID = CAR.ID AND MP2.METADATA_TYPE_ID = 2 AND MP2.Value='2010' 
AND MP3.CAR_ID = CAR.ID AND MP3.METADATA_TYPE_ID = 3 AND MP3.Value='Blue' 

所以,这一切都取决于你的需求。但鉴于你的情况,我的建议是元数据格式。

(但做样板清理第一 - 没有重复的场,1:N的数据对自己的表,而不是像COLOR1,COLOR2,COLOR3,这种东西直列领域;))

4

我想最明显的问题是,那么,为什么不能有一个表car_attrs(汽车,ATTR,价值)?每个属性是一行。大多数查询都可以重写为使用此表单。

+0

我第二。我在多个dbs中使用这种方案,甚至不能提供产品的类型,就像你的例子。是一个很好且最快速的解决方案,并且可以扩展。 – kms

-2

如果您有更改属性,请考虑将它们存储在一个XML列或文本结构中的一列中。这个结构不是关系的。最重要的属性将被复制到其他列中,因此您可以创建查询来搜索它们,因为Blob不能从SQL查询中搜索。这将减少该表中的列数量并允许在不更改数据库模式的情况下进行扩展。

正如其他人所建议的,如果你想在一个表中的所有属性,然后使用属性表来定义它们。那么将取决于您的要求和应用程序的需求。

2

如果它是所有关于功能,创建一个features表,列出你所有的功能为行,给他们某种自动ID,并创建一个car_features与外键到这两个cars表和你features表将汽车与特征联系起来,也许还有与这种关系相关的任何价值(一个乘客电动座椅等)。