归一化,非规范化,还是什么?用于在Survey数据库中存储响应的表

时间:2012-03-04 15:39:36

标签: django orm polymorphism relational-database normalization

即使我使用Django的ORM来实现这些表,我也故意将其作为一般性问题进行构建。 Here are my Django models如果你想看一眼。

谜语

我有几个表有以下关系:

Survey <--m2o-- Page <--m2o-- Category <--m2o-- Question <--m2o-- Choice <--?-- Response
|               |             |                 |                 |
|- name         |-number      |- name           |- sortid         |- sortid
                              |- sortid         |- text           |- text
                              |- text           |- short
                                                |- qtype

m2o是多对一的简写,每个表都有一个隐含的主键,我的问题是关于如何组织响应表。

响应表应该与User表有某种关系(取决于表定义,这可能是一对一或多对一)。该表的目的是存储用户对特定问题的回答。我遇到的问题是,根据问题类型,我需要在Response表中将响应存储在不同的列类型中。例如,表可能类似于:

| user | (question) | (qtype)         | choice    | response                      |
|------+------------+-----------------+-----------+-------------------------------|
| 1    | Q1         | Select One      | A         | False                         |
| 1    | ''         | ''              | B         | False                         |
| 1    | ''         | ''              | C         | True                          |
| 1    | ..         | ''              | D         | False                         |
| 1    | Q2         | Select Multiple | 1         | True                          |
| ''   | ''         | ''              | 2         | True                          |
| ''   | ''         | ''              | 3         | False                         |
| ''   | ''         | ''              | 4         | True                          |
| ''   | Q3         | Long Text       | NULL      | "It was the best of times..." |
| ''   | Q4         | Select Explain  | A         | False                         |
| ''   | ''         | ''              | B         | False                         |
| ''   | ''         | ''              | C         | False                         |
| ''   | ''         | ''              | D (other) | True                          |
| ''   | ''         | ''              | Explain   | "I actually prefer bananas."  |

为了清晰起见,我添加了列,这些列将由关系隐式定义,因此不会出现在实际表中。它们用( )表示。此外,choice实际上是外键。

似乎响应列可能需要是文本列。将其分成两列或更多列,例如response-textresponse-boolean会让人觉得麻烦。我们可以轻松地为单个用户提供数百行。

我还想过组织这样的表:

| user | survey | response (key-value store)                 |
|------+--------+--------------------------------------------|
|    1 |      1 | {"q1": "C", "q2": "1,2,4"                  |
|      |        | "q3": "It was the best of times..."        |
|      |        | "q4": "Other: I actually prefer bananas."} |
|    2 |      1 | {...}                                      |
|    3 |      1 | {...}                                      |

您如何定义此表,以及为什么?

如果你在什么情况下解释你的定义不会很好的话,可以给予奖励。

如果你想想象我的情况,这里有一些关于我背景的笔记:

  • 在调查期间,响应表可能会更新几次,但之后不会更新。此特定表是OLAP,或主要是读取。我将要做的唯一查询是在商业软件包中导出表格进行统计分析。
  • 来自不同用户的回复很少相同(从高级别开始)
  • 在调查管理会话期间,只有15个用户将同时连接到应用程序,因此性能不是问题。存储后,只有一个用户(我)会查看数据。

我怀疑我的情况接近N1NF on Wikipedia的例子。

这个表应该是多态的吗?

我刚刚听说过多表继承或多态,我不知道如何将它应用于这个问题。具体来说,我不确定哪些表会从继承中受益。例如,Response应该扩展选择吗? Page扩展调查吗?

1 个答案:

答案 0 :(得分:4)

我是首席架构师&amp; http://360test.nl/的开发人员使用调查来衡量团队绩效等。

我们的基本表格结构与您的不同。

回答存储在一个相当简单的表格中:

ID | Participation | Question | RawValue

Participation是一个用户参与一项调查的ID。 Question是调查中一个问题的ID。 RawValue存储一个答案。它的格式取决于问题类型。对于更复杂的json构造,它可以是单个数字(对于简单的“选择一个”问题)(例如,对于“在Y选项上分配X点”类型的问题)。问题类型知道如何序列化/反序列化数据可用的东西。

我们不在表格中使用继承。如果我们需要调查答案的在线查询(“调查xyz中有多少用户选择答案3”),这是有道理的,但我们不需要这样做。因此,我们可以使用我们简单的“通用”RawValue列。当我们显示调查结果时,将加载所有答案,对其值进行反序列化并根据问题类型进行评估。 如果我们需要更多特殊报告,我们会离线生成它们并将结果存储在某处。

我认为,即使您建议的方法(将所有答案都存储在一列中)也可以为我们工作,因为我们无论如何都会在执行评估时加载整个数据。

我并不是说我们的方法是最好的,但它对我们有用。

总的来说 - 规范化是一个重要的话题。但这并不意味着,一切都需要规范化。虽然我将核心域模型的持久表示归一化,但我有时会在数据库中存储严重非规范化的数据,以便从域模型生成报告。您知道它是非规范化的以及数据的来源非常重要。

我使用我认为CQRS架构编写软件,我学到的一件事是非规范化可能是一件非常好的事情。一些CQRS专家建议每个网页使用一个表,其中包含该页面所需的所有(非规范化)数据。虽然这不一定是您应该始终做的事情,但它表明在所有情况下都不需要教科书规范化。