【问题标题】:Tricky database design棘手的数据库设计
【发布时间】:2011-04-22 21:39:42
【问题描述】:

我需要设计一个数据库来存储用户值:对于每个用户,都有一组特定的列。

例如,Jon 想要将值存储在具有 2 列的表中:姓名、年龄。

Paul 想要将值存储在一个 3 列的表中:水果、颜色、重量。

此时,我有两个选择。

选项 1 - 将数据存储为文本值

我会有一个包含用户偏好的第一个表“个人资料”:

+----+---------+--------+-------------+
| id | user_id | label  | type        |
+----+---------+--------+-------------+
|  1 |       1 | name   | VARCHAR(50) |
|  2 |       1 | age    | INT         |
|  3 |       2 | fruit  | VARCHAR(50) |
|  4 |       2 | color  | VARCHAR(50) |
|  5 |       2 | weight | DOUBLE      |
+----+---------+--------+-------------+

然后将数据作为文本存储在另一个表中:

+----+------------+--------+
| id | id_profile | value  |
+----+------------+--------+
|  1 |          1 | Aron   |
|  2 |          2 | 17     |
|  3 |          1 | Vince  |
|  4 |          2 | 27     |
|  5 |          1 | Elena  |
|  6 |          2 | 78     |
|  7 |          3 | Banana |
|  8 |          4 | Yellow |
|  9 |          5 | 124.8  |
+----+------------+--------+

之后,我将以编程方式创建并填充一个干净的表。

选项 2 - 每种类型一列

在这个选项上,我会有一个像这样的第一个表“profiles2”:

+----+---------+--------+------+
| id | user_id | label  | type |
+----+---------+--------+------+
|  1 |       1 | name   |    3 |
|  2 |       1 | age    |    1 |
|  3 |       2 | fruit  |    3 |
|  4 |       2 | color  |    3 |
|  5 |       2 | weight |    2 |
+----+---------+--------+------+

与一组类型对应的类型: 1=INT , 2=DOUBLE , 3=VARCHAR(50)

还有这样的数据表:

+----+-------------+-----------+--------------+---------------+
| id | id_profile2 | int_value | double_value | varchar_value |
+----+-------------+-----------+--------------+---------------+
|  1 |           1 |      NULL |         NULL | Aron          |
|  2 |           2 |        17 |         NULL | NULL          |
|  3 |           1 |      NULL |         NULL | Vince         |
|  4 |           2 |        27 |         NULL | NULL          |
|  5 |           1 |      NULL |         NULL | Elena         |
|  6 |           2 |        78 |         NULL | NULL          |
|  7 |           3 |      NULL |         NULL | Banana        |
|  8 |           4 |      NULL |         NULL | Yellow        |
|  9 |           5 |      NULL |        124.8 | NULL          |
+----+-------------+-----------+--------------+---------------+

这里我有更干净的表,但仍然是一个程序化技巧来实现所有东西。

问题

有人遇到过这种情况吗?

你觉得我的两个选项怎么样?

有没有更好的解决方案,不那么棘手?

发送很多!

编辑 再次嗨,

我的模型有一个错误:无法检索“一行”信息;即“值”表中的信息不是可排序的。

在对 EAV 模型进行了一些思考之后,它显示不适合,因为它不是为存储数据而设计的,而是用于存储特定信息的。

然后我以这个模型结束: 第一表“标签”:

+----+------------+------+----------+
| id | profile_id | name | datatype |
+----+------------+------+----------+
|  1 |          1 | 1    | Nom      |
|  2 |          1 | 1    | Age      |
|  3 |          2 | 2    | Fruit    |
|  4 |          2 | 2    | Couleur  |
|  5 |          2 | 2    | Poids    |
+----+------------+------+----------+

然后是一个非常简单的“节点”表,只是为了跟踪信息行:

+----+------------+
| id | profile_id |
+----+------------+
|  1 |          1 |
|  2 |          1 |
|  3 |          2 |
|  4 |          2 |
+----+------------+

以及对应不同数据类型的一组表:

+----+---------+----------+--------+
| id | node_id | label_id | value  |
+----+---------+----------+--------+
|  1 |       1 |        1 | John   |
|  2 |       2 |        1 | Doe    |
|  3 |       3 |        3 | Orange |
|  4 |       3 |        4 | Orange |
|  5 |       4 |        3 | Banane |
|  6 |       4 |        4 | Jaune  |
+----+---------+----------+--------+

使用此模型,查询正常。数据输入有点棘手,但我会用干净的代码来管理。

干杯

【问题讨论】:

  • 这真的是无限列的场景还是你有一个固定的数字,比如 50 以下?无限规模的不同解决方案与花时间创建 50 列的人。

标签: mysql sql database


【解决方案1】:

看看EAV data models

【讨论】:

  • 看问题示例,我的第一感觉也是EAV。 Pro/Con - 设计合理的 EAV 方案理论上可以无限定制;几乎所有 EAV 实现都牺牲了 RDBM 服务器可以提供的任何/所有支持,将约束和完整性责任置于应用程序手中。
  • @David:通常,EAV 数据库中约束和数据完整性的责任落在每个临时用户的肩上。不漂亮。
  • @David 更不用说像有多少香蕉超过 80 岁这样的简单查询是多么痛苦
  • EAV 让我想起了一个日常的 wtf,我看到他们为在他们的数据库中实现一个数据库而感到自豪。只有在您忘记要强制执行的规则之前,失去参照完整性才是好事(当您睡眠过多或将项目交给另一个开发人员时会发生这种情况。显而易见的解决方案是永不睡眠。)
  • 这个 EAV 的好关键字。这确实或多或少是我所说的选项 1。性能和引用完整性的损失应该是无害的,因为我不必执行复杂的请求。
【解决方案2】:

选项 3:制作两个不同的表。

一张桌子显然是供人使用的。另一个显然是水果。它们应该在不同的表中。

【讨论】:

  • 是也不是,这适合我的例子,但它不可扩展;我需要与用户一样多的“表格”。
  • 我以前在其他问题中看到过这种情况,但我永远无法得到明确的答案:为什么需要每个用户都能够以这种方式输入他们自己的数据?对我来说,这表明设计存在严重缺陷。架构应该规定用户可以存储哪些数据,而不是相反。
  • 我同意你的观点。但是我必须建立一个模型,每个用户都可以定义自己的仪表板数据。 Paul 登录,他说“我想跟踪我的客户的姓名和年龄”;然后他输入数据。 (等等,彼得想跟踪他的羊的重量......)。
【解决方案3】:

为什么不只是有一个包含名称和 ID 的用户表,一个包含键值对的 userValues 表?那是约翰可以有键“fruit”和值“mango”,另一个键“轮胎”和值“goodyear”。鲍勃可以有键“coin”和值“penny”和键“age”和值“42”。任何人可以具有他们喜欢的任何值,并且您具有最大的灵活性。速度不会很好,并且您必须将字符串转换为值,但这始终是一种权衡。

干杯, 丹尼尔

【讨论】:

  • 嗨,你能解释一下与选项 1 的区别吗?
  • 第二张表只有两列,Key和Value,所以完全通用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-07
  • 2016-02-17
  • 1970-01-01
相关资源
最近更新 更多