具有动态发展维度的事实的良好(==快速)存储策略?

时间:2008-11-04 12:36:50

标签: database-design

我需要在数据库中存储大量计量数据。 记录由标识数据源,时间戳和值的标识组成。稍后通过id及其时间戳检索记录。

根据我之前的经验(我正在开发过去五年中一直在高效使用的应用程序的后续版本),磁盘i / o是数据检索的相关性能瓶颈。 (另见this other question of mine)。

由于我从不寻找单行但总是寻找与一系列ID和时间戳匹配的(可能很大的)行组,因此非常明显的优化似乎是存储更大的压缩数据块由更小的索引访问(例如按天数),并且应用程序解压缩并即时过滤

我正在寻找的是决定将哪一部分数据放入一个块的最佳策略。在完美的世界中,每个用户请求将通过检索一个数据块并使用其中的大部分或全部来完成。所以我想最小化我必须为每个请求加载的块数量,并且我希望最大限度地减少每个块的多余数据。

我将在下面发布一个包含我的想法的答案,并将其设为社区属性,以便您可以对其进行扩展。当然,如果您采用不同的方法,请发布自己的方法。

ETA:S. Lott已发布下面的this answer,即使我无法直接使用它,也会对讨论有所帮助(请参阅我的评论)。这里的要点是我的“事实”的“维度”是(并且应该)受最终用户的影响并随着时间的推移而变化。这是应用程序的核心功能,实际上是我首先解决这个问题的原因。

5 个答案:

答案 0 :(得分:2)

“与一系列ID和时间戳匹配的行组”

您有两个维度:来源和时间。我确定数据源有很多属性。我知道,时间有很多属性(年,月,日,小时,星期几,星期,季度,财政期间等等)。

虽然您的事实只是“ID”和时间戳,但它们可能具有数据源维度和时间维度的FK。

作为星型模式查看,查找“匹配一系列ID的行组”的查询可能 - 更恰当地 - 是具有公共数据源属性的一组行。它不是一个随机的ID集群,而是由维度的某些常见属性定义的ID集群。

一旦定义了数据源维度的这些属性,您的“分块”策略应该更加明显。

此外,您可能会发现某些数据库产品的位映射索引功能可以简单地将您的事实存储在一个普通的表中,而不会冒出任何块设计。

如果位映射索引仍然不够快,那么也许,你必须将数据源属性反规范化为维度和事实,然后在这个维度属性上对事实表进行分区。

答案 1 :(得分:1)

选项3:

找到一个能完成这项工作的聪明的数据库功能。

答案 2 :(得分:1)

选项1& 3您需要非常了解最常见的查询。使用80/20规则,不要尝试使所有查询在同一级别执行。

选项2听起来很有趣,但是簿记可能会有点毛茸茸。

选项3有一些承诺,它可以解决性能问题,只需对应用程序进行很少或不进行任何更改。我建议调查两件事:

  1. 表格分区。 Oracle和MS Sql Server(以及其他人,我敢肯定)支持在物理上按表格对数据进行分组(在本例中为日期/时间戳)。您可以将分区配置为驻留在不同的物理设备上,以便在硬件之间分配负载,从而有望减少延迟。
  2. 使用包含的列进行索引。这总是让我觉得反直觉,但是通过将要检索的列添加到索引中,可以执行整个查询而无需访问实际的表。
  3. 这两个选项的缺点是变异操作(插入/删除),其中索引必须更新。

    您可能想要尝试1和3的组合(它们在很多方面相似),味道为#2。跟踪最常查询的时间段的统计信息(选项2),并定期重新审视1或3中的策略,直到核心查询的性能可以接受为止。

答案 3 :(得分:0)

选项1:

很好地猜测将要加载到一起的内容并将其放在一个,而不是太大的块中。示例:每天有一个块

优点:

  • 简单,数据查询可以通过简单的计算完成(请求时间范围涉及哪些天?),而不是保留索引的位置。
  • 无需工具即可轻松理解存档结构

缺点:

  • 不是最佳表现
  • 不适应应用程序用户的行为改变

答案 4 :(得分:0)

选项2:

开发一种聪明的“再平衡策略”,它可以跟踪加载到一起的数据,并尝试将经常加载的内容组合在一起。这可能包括将行的副本保存在多个块中。

优点:

  • 几乎可以任意智能
  • 可以在性能方面非常有效
  • 允许不断发展的策略

缺点:

  • 几乎可以随意开发,测试和调试
  • 在自我优化开始之前可能会遇到性能不佳的问题
  • 记录的多个副本可能会膨胀存储
  • 我觉得这应该由数据库完成