这个表对 mysql 有什么好处吗?我希望将来能够灵活地用于这种类型的数据存储。对于这种表结构,您不能使用主键,而只能使用索引...
我是否应该更改表的格式以具有标题 - 主键、宽度、长度、空间、耦合...
ID_NUM Param Value
1 Width 5e-081
1 Length 12
1 Space 5e-084
1 Coupling 1.511
1 Metal Layer M3-0
2 Width 5e-082
2 Length 1.38e-061
2 Space 5e-081
2 Coupling 1.5
2 Metal Layer M310
不,这对于关系数据库来说是一个糟糕的设计。 这是Entity-Attribute-Value设计的示例。 它很灵活,但它打破了关系数据库的大多数规则。
在深入了解 EAV 设计作为灵活数据库的解决方案之前,请阅读以下故事:Bad CaRMa。
更具体地说,EAV 的一些问题包括:
value
列必须是长 VARCHAR(或者添加多个值列,每种数据类型一个,然后为您存储的每个属性选择一种类型)。使用 EAV 设计时,查询也非常复杂。 Magento 是一个开源电子商务平台,广泛使用 EAV,许多用户表示如果需要自定义报告,它非常慢且难以查询。
为了实现关系,您应该将每个不同的属性存储在其自己的列中,并具有自己的名称和适当的数据类型。
我在演示文稿SQL 中的实用面向对象模型、博客文章EAV FAIL以及我的书SQL 反模式第 1 卷:避免数据库编程的陷阱中写了更多有关 EAV 的内容。
EAV model (Entity–Attribute–Value)
它有几个缺点,例如在执行引用完整性约束方面存在严重困难。此外,您必须提出的查询将比作为您的第二个建议的规范化表(包含列的表:
Primary Key, Width, Length, Space, Coupling, etc
)更复杂一些。
所以,对于简单的项目,不要使用EAV模型。
如果您的计划是针对更复杂的项目并且您想要最大的灵活性,也不要使用 EAV。你应该研究一下
6NF (6th Normal Form)
,这在 MySQL 中更难实现,当然也不是一件容易的事。但如果你成功了,你将同时获得好处:灵活性和标准化到最高水平(有些人将“EAV”称为“6NF 做得错误”)。
根据我的经验,需要非常仔细地考虑按行存储字段的想法 - 尽管它看起来有很多优点,但它使许多常见任务变得更加困难。
积极的一面:它可以轻松扩展,无需更改数据库结构,并在某些方面抽象了数据存储的细节。
消极的一面:您需要查看 DBMS 中自动提供的按列存储字段的所有日常事务:简单的内/外连接、一条语句插入/更新、唯一性、外键和其他数据库级约束检查,简单的搜索结果过滤广告排序。
在您的架构中考虑一个查询,以返回 MetalLayer=X 且宽度在 y 和 z 之间的所有项目 - 结果按耦合按长度排序。与使用列存储特定字段相比,此查询对于您来说构建起来要困难得多,对于 DBMS 来说执行起来要困难得多。
总的来说,我唯一一次使用像您建议的结构是在需要临时添加随机非结构化附加数据的情况下。在我看来,如果我无法使更传统的表结构发挥作用,这将是最后的策略。
这里需要考虑一些事情:
没有单一主键。这可以通过使主键由两列组成来克服(如 Carl T 的第二个示例)
Param 列是重复的,要对其进行标准化,您应该查看 MGA 的示例。
第三,“金属层”列是一个字符串,而不是像其他列一样的浮点值。
所以最好选择这样的表:
create table yourTable(
ID int primary key,
ParamId int not null,
Width float,
Length float,
Space float,
Coupling float,
Metal_layer varchar(20),
Foreign key(ParamID) references Param(ID),
Value varchar(20)
)
create table Param(
ID int primary key,
Name varchar(20)
)
在创建专门供将来使用的表时,您要问的主要问题是如何检索这些数据以及它的用途。就我个人而言,我总是有一个唯一的标识符,通常是表的 ID。
查看您的列表似乎没有任何唯一定义条目的内容,因此您将无法跟踪重复条目或唯一检索记录。
如果您想保留此设计,您可以创建一个由名称和参数值组成的复合主键。
CREATE TABLE testtest (
ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Name VARCHAR(100) NOT NULL,
value number NOT NULL
/*add other fields here*/
);
CREATE TABLE testtest (
name VARCHAR(100) NOT NULL,
value int NOT NULL,
/*add other fields here*/
primary key(name,value)
);
那些创建表的示例表达了上面提到的 2 个选项。