以这种方式构建SQL表的缺点是什么?

时间:2016-08-26 15:19:42

标签: mysql sql database sqlite normalization

我想说我要创建一个这样的表:

id | some_foreign_id | attribute | value
_________________________________________
1           1            Weight     100
2           1            Reps       5
3           2            Reps       40
4           3            Time       10
5           4            Weight     50
6           4            Reps       60

与以这种方式表示的相同数据

id | some_foreign_id | weight | reps | time
____________________________________________
1           1           100      5     NULL
2           2           NULL     40    NULL
3           3           NULL     NULL  10
4           4           50       60    NULL

因为在这种情况下id = foreign_id我认为我们可以将这些列附加到foreign_id所指的任何表中。

我认为大多数人会压倒性地说后一种方法是公认的做法。

前一种方法是否被认为是一个坏主意,即使它没有导致任何NULL?这两种方法之间的权衡是什么?看起来前者可能更加多样化,但却没有真正明确定义的结构,但我不知道这是否会导致其他后果。我可以想象在后一个例子中有大量列的情况,其中大多数是NULL,并且可能只填充了三个不同的值。

5 个答案:

答案 0 :(得分:1)

EAV是你的第一个例子所在的模型。它有一些优点,但是你在mysql中并且mysql不能处理这个问题。正如在这个线程Crosstab View in mySQL?中指出的那样,mysql缺少其他数据库所具有的功能。 Postgres和其他数据库有一些更有趣的函数PostgreSQL Crosstab Query,这使得这更容易。在MSSQL世界中,这被称为稀疏填充的列。我发现柱状结构实际上很适合这个(vertica或高端oracle)

优点:

  • 向此添加新列比更改表架构要容易得多。如果您不确定未来的列名是什么,这就是要走的路

  • 稀疏填充的列会导致表中充满空值和冗余数据。您可以设置逻辑来为列创建“默认”值...如果没有为此属性指定值,则使用此值。

缺点:

  • 根据上述评论,特别难以在MySQL中编程。并非所有SQL开发人员都熟悉该模型,您可能会意外地为新资源实施更陡峭的学习曲线。

  • 不是最具扩展性的。索引是一个挑战,你需要解决(草莓在评论中的输入就是这个,你的值列基本上被强制为Varchar而且索引不好,也不容易搜索...欢迎来到表扫描地狱)。虽然你可以通过第三个表来解决这个问题(比如你在创建日期和关闭日期等日期查询。创建第三个'控制'表,其中包含那些经常查询的列和索引......从那里引用EAV表)或创建多个EAV表,每种数据类型一个。

答案 1 :(得分:0)

第一个是正确的。

  • 如果以后要更改属性数,则无需更改数据库结构。

    • 更改数据库结构可能会导致您的应用中断。
  • 如果null的数量太大,则会浪费大量存储空间。

答案 2 :(得分:0)

我对此的看法 第一个我可能会使用,如果我有很多不同的属性和值,我想以更动态的方式添加,如用户标签或用户特定信息等,

我可能会使用第二个,如果我只有三个属性(如你的例子中),权重,代表,时间并且不需要任何动态或需要添加更多属性(如果是这种情况,我只会添加另一列)

我会说两种作品,就像你自己说的那样,“前者可能更具多样性”。两种方式都需要它们自己的结构来提取,处理和存储数据:)

编辑:对于第一个实现第二个结构的人,你必须为你想要包含在数据提取中的每个属性添加一个连接。

答案 3 :(得分:0)

我认为第一种方式更有利于规范化。您甚至可以创建一个包含属性的新表:

Controller.Initialize

然后将第二列变为外国ID。这样可以节省空间,并且可以节省错误输入属性名称的风险。像这样:

id  attribute
______________
1   reps
2   weight
3   time

答案 4 :(得分:0)

正如其他人所说,第一种方式是更好的方式。为什么?好吧,它使结构正常化。参考:https://en.wikipedia.org/wiki/Database_normalization

正如该文章所述,规范化减少了数据库的大小和范围。允许轻松扩展。