【问题标题】:mysql table structure proposal?mysql表结构建议?
【发布时间】:2011-11-29 23:47:21
【问题描述】:

这个表对mysql有用吗?我想在未来为这种类型的数据存储提供灵活性。使用这种表结构,您不能使用 PRIMARY KEY 而是使用索引...

我是否应该将表格的格式更改为具有标题 - 主键、宽度、长度、空格、耦合...

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

【问题讨论】:

  • Shef,它可以工作,但不能标准化。
  • 我认为主键必须是唯一的?
  • 这不能归一化,因为它不是关系。

标签: mysql entity-attribute-value


【解决方案1】:

不,这对于关系数据库来说是一个糟糕的设计。这是Entity-Attribute-Value 设计的一个示例。它很灵活,但它打破了关系数据库的大部分规则。

在您深入了解 EAV 设计作为灵活数据库的解决方案之前,请阅读以下故事:Bad CaRMa

更具体地说,EAV 的一些问题包括:

  • 如果不查询任何给定 ID_NUM,您不知道它们存在哪些属性。
  • 您不能将任何属性设为强制性,相当于 NOT NULL。
  • 您不能使用数据库约束。
  • 不能使用 SQL 数据类型; value 列必须是长 VARCHAR。
  • 特别是在 MySQL 中,每个 VARCHAR 都存储在自己的数据页上,因此非常浪费。

使用 EAV 设计时,查询也非常复杂。 Magento 是一个开源电子商务平台,广泛使用 EAV,很多用户表示如果需要自定义报告,它非常慢且难以查询。

要保持关系,您应该将每个不同的属性存储在其自己的列中,并具有自己的名称和适当的数据类型。

我在我的演示文稿Practical Object-Oriented Models in SQL 和我的博文EAV FAIL 以及我的书中SQL Antipatterns: Avoiding the Pitfalls of Database Programming 中写了更多关于EAV 的内容。

【讨论】:

    【解决方案2】:

    你的建议叫EAV model (Entity–Attribute–Value)

    它有几个缺点,例如在执行参照完整性约束方面存在严重困难。此外,您必须提出的查询将比使用规范化表作为您的第二个建议(带有列的表:Primary Key, Width, Length, Space, Coupling, etc)稍微复杂一些。

    所以,对于一个简单的项目,不要使用 EAV 模型。

    如果您的计划是针对更复杂的项目并且您希望获得最大的灵活性,那么也不要使用 EAV。你应该看看 6NF (6th Normal Form) ,它更难实现,在 MySQL 中肯定不是一件容易的事。但如果你成功了,你将拥有两样东西:灵活性和最高水平的规范化(有些人将“EAV”称为“6NF 做错了”)。 p>

    【讨论】:

      【解决方案3】:

      根据我的经验,需要非常仔细地考虑这种按行存储字段的想法 - 尽管它似乎有很多优点,但它使许多常见任务变得更加困难。

      积极的一面:它很容易扩展,无需更改数据库的结构,并且在某些方面抽象了数据存储的细节。

      不利的一面:您需要查看在 DBMS 中自动按列存储字段的所有日常事物:简单的内部/外部连接、一条语句插入/更新、唯一性、外键和其他数据库级别约束检查,简单过滤搜索结果的广告排序。

      考虑在您的架构中查询返回所有具有 MetalLayer=X 和宽度在 y 和 z 之间的项目 - 结果按 Coupling 按长度排序。与使用列存储特定字段相比,此查询对您而言更难构建,对 DBMS 而言也更难执行。

      总的来说,我唯一一次使用您建议的结构是在需要临时添加随机非结构化附加数据的情况下。在我看来,如果我无法让更传统的表结构发挥作用,这将是最后的策略。

      【讨论】:

        【解决方案4】:

        这里有几点需要考虑:

        没有单一的主键。这可以通过使主键包含两列来克服(如 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)
        )
        

        【讨论】:

          【解决方案5】:

          在创建专门供将来使用的表时,您必须问的主要问题是如何检索这些数据以及它有什么用途。就我个人而言,我总是有一个唯一标识符,通常是表的 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)
          );
          

          那些创建表的例子表达了上面提到的两个选项。

          【讨论】:

            猜你喜欢
            • 2011-05-02
            • 2012-01-06
            • 1970-01-01
            • 2011-11-06
            • 1970-01-01
            • 1970-01-01
            • 2021-01-02
            • 2011-10-29
            • 2013-06-12
            相关资源
            最近更新 更多