我需要在数据库中存储大量计量数据。 记录由标识数据源,时间戳和值的标识组成。稍后通过id及其时间戳检索记录。
根据我之前的经验(我正在开发过去五年中一直在高效使用的应用程序的后续版本),磁盘i / o是数据检索的相关性能瓶颈。 (另见this other question of mine)。
由于我从不寻找单行但总是寻找与一系列ID和时间戳匹配的(可能很大的)行组,因此非常明显的优化似乎是存储更大的压缩数据块由更小的索引访问(例如按天数),并且应用程序解压缩并即时过滤。
我正在寻找的是决定将哪一部分数据放入一个块的最佳策略。在完美的世界中,每个用户请求将通过检索一个数据块并使用其中的大部分或全部来完成。所以我想最小化我必须为每个请求加载的块数量,并且我希望最大限度地减少每个块的多余数据。
我将在下面发布一个包含我的想法的答案,并将其设为社区属性,以便您可以对其进行扩展。当然,如果您采用不同的方法,请发布自己的方法。
ETA:S. Lott已发布下面的this answer,即使我无法直接使用它,也会对讨论有所帮助(请参阅我的评论)。这里的要点是我的“事实”的“维度”是(并且应该)受最终用户的影响并随着时间的推移而变化。这是应用程序的核心功能,实际上是我首先解决这个问题的原因。
答案 0 :(得分:2)
“与一系列ID和时间戳匹配的行组”
您有两个维度:来源和时间。我确定数据源有很多属性。我知道,时间有很多属性(年,月,日,小时,星期几,星期,季度,财政期间等等)。
虽然您的事实只是“ID”和时间戳,但它们可能具有数据源维度和时间维度的FK。
作为星型模式查看,查找“匹配一系列ID的行组”的查询可能 - 更恰当地 - 是具有公共数据源属性的一组行。它不是一个随机的ID集群,而是由维度的某些常见属性定义的ID集群。
一旦定义了数据源维度的这些属性,您的“分块”策略应该更加明显。
此外,您可能会发现某些数据库产品的位映射索引功能可以简单地将您的事实存储在一个普通的表中,而不会冒出任何块设计。
如果位映射索引仍然不够快,那么也许,你必须将数据源属性反规范化为维度和事实,然后在这个维度属性上对事实表进行分区。
答案 1 :(得分:1)
选项3:
找到一个能完成这项工作的聪明的数据库功能。
答案 2 :(得分:1)
选项1& 3您需要非常了解最常见的查询。使用80/20规则,不要尝试使所有查询在同一级别执行。
选项2听起来很有趣,但是簿记可能会有点毛茸茸。
选项3有一些承诺,它可以解决性能问题,只需对应用程序进行很少或不进行任何更改。我建议调查两件事:
这两个选项的缺点是变异操作(插入/删除),其中索引必须更新。
您可能想要尝试1和3的组合(它们在很多方面相似),味道为#2。跟踪最常查询的时间段的统计信息(选项2),并定期重新审视1或3中的策略,直到核心查询的性能可以接受为止。
答案 3 :(得分:0)
选项1:
很好地猜测将要加载到一起的内容并将其放在一个,而不是太大的块中。示例:每天有一个块
优点:
缺点:
答案 4 :(得分:0)
选项2:
开发一种聪明的“再平衡策略”,它可以跟踪加载到一起的数据,并尝试将经常加载的内容组合在一起。这可能包括将行的副本保存在多个块中。
优点:
缺点: