【问题标题】:Database design of survey query system调查查询系统的数据库设计
【发布时间】:2010-10-09 18:12:18
【问题描述】:

我正在开发一个所谓的行为风险因素监测系统 (BRFSS),这是一个处理每年都会出现的问卷的网络查询系统。

我很难为它想出一个合适的数据库设计。问题是:每份问卷包含大约 80 个问题,包括人口统计信息,例如年龄,教育等,以及调查问题,例如吸烟、健康等。每年,有些问题会发生变化,有些则不会。数据源是一个包含 80 多列的 Excel 文件。系统必须支持以下查询:

SELECT [question var], [demo var], count(*) 
FROM survey 
WHERE age in (...) AND educ in (...) [etc] 
GROUP BY <question var>

数据是只读的,即。导入后永不改变。所以它不必被规范化太多。直观地说,类似电子表格的表格会做得很好。速度和空间。但是,这成为了一个问题,因为问题会发生变化,那么我们无法将所有数据保留在此表中,因为跨年度查询是必要的。

我尝试将回复标准化为三个表格:问题、回复和 response_values,它们可以支持问题的变化。但随后响应表跨越了 98*14268 = 1,398,264 行一年!这真的很大。查询速度很慢!

我应该如何设计数据库?任何帮助表示赞赏!提前致谢!

ps。我正在使用 Python+Django+Sqlite。

【问题讨论】:

    标签: python database django sqlite


    【解决方案1】:

    我在 stackoverflow 上发帖后也一直在思考。以下是我如何使用非规范化宽表(80 多列)来支持每年更改问题并汇总交叉表。请发表评论。谢谢

    1. 为每一年创建一个新表格,将问题放在列上 例如

      id 年龄 性别 教育 收入 ...抽艾滋病毒饮料 ...

    2. 创建两个表:Question 和 Query_Year,一个多对多表 Question_Year。然后我们可以填充指定年份可用的问题列表,反之亦然。

    3. 一年内的查询很容易。并且查询跨年,我们可以使用一个 UNION 操作符。由于问题应该在所选年份之间兼容,因此 UNION 是合法的。 例如

      选择 * 从 ( SELECT id, , , COUNT() 从survey_2001 联合所有 SELECT id, , , COUNT() FROMsurvey_2003 联合所有 SELECT id, , , COUNT(*) FROMsurvey_2004 联合所有 等等等等 ) 在哪里 ( 年龄 (...) 和 EDUC in (...) AND 等等等等 ) 分组,

    我认为 UNION 是一个不应该降低 RDBMS 效率的关系运算符。因此,如果我通过联合合并许多表并没有什么坏处。该引擎还可以进行一些查询分析以提高速度。

    我认为这个足够简单。请发表评论。谢谢!

    【讨论】:

      【解决方案2】:

      您至少需要 3 张桌子:

      1) Questions 包含每个问题的文本,带有自动增量 ID 键

      例如:(123,“你的头发是什么颜色的?”)

      2) Questionaires,将 Q# 映射到问题上。

      例如)问题 #3 上的问题 #10 映射到问题 #123。

      3) Answers,将每个受访者与他们的问卷和数据联系起来

      例如)Bob 对问卷 #3 的问题 #10 的回答是“棕色”。

      您应该会看到使用现有问题添加新问卷并添加新问题是多么容易。是的,会有很大的表,但是一个好的数据库引擎应该能够轻松处理 1M 条目。您可以使用分区来提高效率,例如按年分区。

      我将把它作为如何将其转换为 sql 的练习。

      【讨论】:

      • 这几乎是我在规范化设计中所做的。在规范化之前,查询很快就会返回。但是使用这种方案,在没有索引和分区的情况下,处理上述查询大约需要 3-4 秒。尽管我可以索引和分区,但想想这不是很理想。
      【解决方案3】:

      听起来像是星型模式的案例。

      你会有一个像这样的(巨大的)事实表:

      question_id、survey_id、age_group_id、health_classifier_id、is_Smoking ...、answer_value

      和非规范化维度表:

      年龄组: group_name, min_age, max_age, age_group_id

      对于这样的系统来说,140 万行听起来并不多。

      某些数据库具有支持对这种模式进行查询的特殊功能:

      在 Oracle 上是:

      • “维度”支持沿维度聚合
      • 位图索引,用于过滤低基数属性,例如 age_group_id 和 is_Smoking
      • 位图连接索引,用于过滤连接表中的低基数属性,即从事实表中选择但过滤年龄组表中的 min_age。
      • 分区表以处理大表
      • 用于预先计算聚合结果的物化视图

      对于这种数据,也有专门的数据库系统,称为多维数据库。

      检查您的数据库是否有类似的结构或考虑切换数据库引擎

      【讨论】:

      • +1:答案是事实表。问卷是一个缓慢变化的维度。
      • 谢谢!但是如果我没记错的话,星级计划将无法处理每年的问卷变化。否则,我们是否应该继续更改事实表?
      【解决方案4】:

      您是否检查过DatabaseAnswers,看看是否有可以用作起点的架构?

      【讨论】:

      • 谢谢!我不知道那个网站。但我怀疑它是否会包括这样的具体案例。无论如何,我会看看。
      • 嗯,有一个问卷 - 复杂的答案。但它使用与我发布的第二个相同的设计。这将导致巨大的表和缓慢的查询。此外,考虑到问题,我更喜欢重量更轻的设计。
      猜你喜欢
      • 1970-01-01
      • 2012-04-25
      • 2011-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-17
      相关资源
      最近更新 更多