我想说我要创建一个这样的表:
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,并且可能只填充了三个不同的值。
答案 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
正如该文章所述,规范化减少了数据库的大小和范围。允许轻松扩展。