我正在考虑两种桌子设计的选择,我不确定每种选择的利弊。
以下是我的情况的一个抽象描述:
我正在跟踪一些数据点(category_id, point_id, value)
大多数时候,我只对数据点的当前值感兴趣。但我需要记录所有的历史价值观,只要有变化。
有时我可能想查看特定点的历史值,但如果这些查询稍微慢一点就可以了。最重要的是,我可以尽快得到所有点的当前值,或者某个特定类别中所有点的当前值。
我正在考虑的两种(可能还有三种)方法:
使用两个单独的表,一个current_vales表和一个history表,每次current_values中的内容发生更改时,都会有一个触发器将一行插入到历史表中。
每行只能使用一个布尔标志isCurrent的表。每当值更改时,将该行标记为不再是当前行,并插入带有更新值的新当前行。
(在每一行上只使用一个带有时间戳的表——那么特定id的当前值就是带有最新时间戳的行。但是作为一个查询来表达似乎很复杂,特别是如果我想得到一个特定类别的所有当前值,甚至不确定如果没有子查询或性能的话我将如何表达)
一次只会有大约3000-5000个当前点,但是这些值的变化频率足够高,每天可以改变多达一半,因此最终会有数十万行历史。
以上每种方法的优缺点是什么(或者还有其他更好的方法我没有提到)?考虑到我的目标是尽快得到当前的一组点,并且可以对历史进行较慢的查询,哪一个是最好的?

最佳答案

选项1和选项2将具有类似的性能-您在选项1中手动“分区”的数据也可以使用聚集索引(IsCurrent作为选项2的第一列)进行管理。您始终可以有一个只给出当前行的视图,在某些方面,这在性能上非常相似,因为更改IsCurrent将物理地移动旧行(由于集群),并添加新行,就像您的触发器将在两个表中删除和插入一样。
您还可以使用MySQL的分区特性。
拥有单个表的单独表或分区的一大好处是以更细粒度的方式控制数据的备份(并可能清除)。
选项1的一个真正的好处是您确实保存了这个小列,当您到达数十亿行时,这可能会有好处。
选项2的一个维护好处是架构始终相同(不必保持更改同步),因为只有一个表。
选项3的性能不会很好,因为当前值的前缘更难找到,也就是说,可变的(尽管使用标识符和时间戳描述的索引来提高性能并非不可能)

10-06 04:53