5

在 SQL 中实现双时态数据库时,通常建议使用以下时间戳:

  • 有效开始
  • 有效结束
  • 交易开始
  • 交易结束

我以前使用过这种方法几次,但我一直想知道为什么只有 3 个时间戳,而将 TransactionEnd 排除在外,并不仅仅是正确的实现。这里的事务时间范围跨越从 TransactionStart 到下一个 TransactionStart。

是否有任何强有力的论据不仅使用 3 个时间戳,这会限制数据库的大小?

4

2 回答 2

3

正如评论中提到的那样,这是为了简单起见,因为没有它进行某些查询会有些困难。

考虑以下示例。John1990 年 1 月 1 日出生在某个地方, Location1但首次登记为 5 日出生。

数据库表 ,Persons现在看起来像这样:

+----------+--------------+------------+----------+------------+----------+
|   Name   | Location     | valid_from | valid_to | trans_from | trans_to |
+----------+--------------+------------+----------+------------+----------+
| John     | Location1    | 01-01-1990 |99-99-9999| 05/01/1990 |99-99-9999|
+----------+--------------+------------+----------+------------+----------+

此时,删除trans_to列不会造成太大麻烦,但假设如下:

几年后,比如 20 岁,John搬迁到Location220 天后通知官员。这将使Persons表格看起来像这样

+----------+--------------+------------+----------+------------+----------+
|   Name   | Location     | valid_from | valid_to | trans_from | trans_to |
+----------+--------------+------------+----------+------------+----------+
| John     | Location1    | 01-01-1990 |99-99-9999| 05/01/1990 |20-01-2010|
| John     | Location1    | 01-01-1990 |01-01-2010| 20/01/2010 |99-99-9999|
| John     | Location2    | 01-01-2010 |99-99-9999| 20/01/2010 |99-99-9999|
+----------+--------------+------------+----------+------------+----------+

假设有人想找出“系统认为约翰现在住在哪里”(交易时间),而不管他实际住在哪里。这可以(大致)通过以下方式在 SQL 中查询

Select  Location
From    Persons
Where   Name = John AND trans_from > NOW AND trans_to < NOW

假设事务结束时间被删除

+----------+--------------+------------+----------+------------+
|   Name   | Location     | valid_from | valid_to | trans_from |
+----------+--------------+------------+----------+------------+
| John     | Location1    | 01-01-1990 |99-99-9999| 05/01/1990 |
| John     | Location1    | 01-01-1990 |01-01-2010| 20/01/2010 |
| John     | Location2    | 01-01-2010 |99-99-9999| 20/01/2010 |
+----------+--------------+------------+----------+------------+

上面的查询当然不再有效,但是在最后一个表中为同一查询制定逻辑会有些困难。由于trans_to缺少 ,因此必须从表中的其他行派生。例如trans_to,第一行的隐式时间(因为它是最旧的条目)是trans_from从第二行开始的,这是两者中较新的。

因此,事务结束时间是9999-99-99,如果该行是最新的,或者它是trans_from紧随其后的行。

这意味着有关特定行的数据不会完全保存在该行中,并且这些行彼此之间形成依赖关系,这(当然)是不需要的。此外,很难确定哪一行是一行的直接后继,这会使查询更加复杂

于 2015-04-16T14:28:00.520 回答
1

在一维时态数据库中仅使用一个时间戳而不是两个时间戳的示例:

我有一家商店,我想记录用户 X 何时在我的商店中。

如果我使用具有开始时间和结束时间的模型,则此信息可以记录为

X,1,2
X,3,4

所以用户 X 在 1 和 2 之间以及 3 和 4 之间在我的商店中。这很清楚,简单明了。

如果我仅使用开始时间作为时间戳对数据进行建模,我将拥有:

X,1
X,2
X,3
X,4

但我如何解释这些数据?X 来自 (1,2) 和 X 来自 (3,4)?还是来自 (2,3) 的 X 和来自 (1,4) 的 X?还是来自 (1,2)、(2,3)、(3,4) 的 X?(4,inf) 中的 X 有效吗?

为了理解这些数据,我需要在我的数据或代码中添加额外的约束/逻辑/信息:也许间隔是不重叠的,也许我为每个对象添加了一个 id,等等。所有这些解决方案并非在所有情况下都有效,可以难以维护等问题。

例如:如果我为每个项目添加一个 id(a,b 在这种情况下),它将导致:

X,a,1
X,a,2
X,b,3
X,b,4

而是将我的数据存储在 2 行 3 列中,我的数据将存储在 4 行 3 列中。使用这个模型不仅我没有任何好处,而且这个模型可以简化为:

X,a, 1,2 
X,b, 3,4

进一步减少到

X, 1,2
X, 3,4
于 2015-04-16T09:40:46.087 回答