使用历史和快照功能的用于部分更改数据点的数据库设计吗?

时间:2018-11-26 10:55:13

标签: sql database-design nosql time-series

我正在从概念上寻找正在解决的最佳实践或解决方案。

我有一组数据点(大约500个),这些数据点随着时间的推移被用户部分更改。重要的是要分辨出在哪个时间点更改了哪些值。数据可能看起来像这样:

数据随时间变化:

+--------------------------------------------------------------------------------------+
|   Date     |  Value no. 1  |  Value no. 2  |  Value no. 3  |  ...  |  Value no. 500  | 
|------------+---------------+---------------+---------------+-------+-----------------|
|  1/1/2018  |               |               |       2       |       |        1        |
|  1/3/2018  |       2       |       1       |               |       |                 |
|  1/7/2018  |               |               |       4       |       |        8        |
| 1/12/2018  |       5       |       3       |               |       |                 |
....

必须有可能在某个时间点拍摄快照,以获取对于该特定时间点有效的完整数据点集,如下所示:

拍摄于1/3/2018的快照将产生:

+---------------------------------------------------------+
|  Value 1  |  Value 2  |  Value 3  |  ...  |  Value 500  | 
|-----------+-----------+-----------+-------+-------------|
|     2     |     1     |     2     |   0   |      1      |

在2018年1月9日拍摄的快照将产生:

+---------------------------------------------------------+
|  Value 1  |  Value 2  |  Value 3  |  ...  |  Value 500  | 
|-----------+-----------+-----------+-------+-------------|
|     2     |     1     |     4     |   0   |      8      |

在2018年1月13日拍摄的快照将产生:

+---------------------------------------------------------+
|  Value 1  |  Value 2  |  Value 3  |  ...  |  Value 500  | 
|-----------+-----------+-----------+-------+-------------|
|     5     |     3     |     4     |   0   |      8      |

以此类推...

我不受特定数据库技术的约束,因此SQL或NoSQL都可以。可能无法满足DB域中的所有要求-有些可能必须用代码解决。但是我的主要问题是哪种数据库技术最适合此任务?

我不确定这是否适合时间序列数据库(TSDB),因为在给定时间仅更改了一部分值,因此知道哪些值已更改很重要。也许我错了?

/克里斯

2 个答案:

答案 0 :(得分:0)

看看SQL Server temporal tables engine,这可能是您的解决方案。这种方法允许运行问题中提到的查询,例如

SELECT * 
FROM my_data   
FOR SYSTEM_TIME AS OF '2018-01-01'

但是,示例中的表似乎很大(可能已规范化)。我建议按某些技术或功能特性(垂直分区)对列进行分组,以避免进一步的维护缺陷。

答案 1 :(得分:0)

我的建议是以稀疏格式对此建模,例如:

CREATE TABLE DataPoint (
    DataID int,               /* 1 to 500 in your example, or whatever you need to identify it*/
    ValidFrom timestamp,  /*default value 01/01/1970-00:00:00 or a suitable "Epoch" */
    ValidUntil timestamp, /*default value 31/12/3999-00:00:00 or again something that is in the far future for your case */
    value Number (7,5)  /* again, this may be any data type, or even more than one field if needed, like Price & Currency
);

我们刚刚定义的是一组数据和每个数据都有特定值的“间隔”,因此,如果您昨天测量了DataPoint 1并获得了89.768的值,您将插入:

DataId = 1 ValidFrom = 26/11 / 2018-14:52:41 ValidUntil = 31/12 / 3999-00:00:00 值= 89.768

然后您明天再对其进行测量并得到:

DataId = 1 ValidFrom = 28/11 / 2018-14:51:23 ValidUntil = 31/12 / 3999-00:00:00 值= 89.443

(假设您也有逻辑,以便在记录新值时更新当前值记录并分配ValidUntil = 28/11 / 2018-14:51:23这并不是真正需要的,但将作为示例查询更简单)。

从现在开始的一个月,您已经对数据#1进行了更多的测量,而在不同的时刻对数据#2至500进行了相同的测量。 您现在想找出今天中午(即一个月前的“ ago”)的值,即27/11/2018:12:00:00:00

Select DataID, Value from DataPoint where ValidFrom <= 27/11/2018:12:00:00 and ValidUntil > 27/11/2018:12:00:00

这将返回:

  001,89.768
  002,45.678
  ...,...
  500,112.809

关于记录执行此操作的人或出于何种原因,您可以单独记录(例如保存DataPoint Id,Timestamp,UserId ...),也可以使其成为原始表的一部分,以便在每次注册新表时您还记录谁测量了它的数据点。