Sql 对于表的历史信息,哪个选项更好?

Sql 对于表的历史信息,哪个选项更好?,sql,database-design,Sql,Database Design,我有一个表a,其中存储了用户可以更新的信息,但由于用户的要求,我需要跟踪信息中的更改。 考虑到: 此信息将在用户需要时显示 信息可以随时更改,但不经常更改,比如说一年更改5次 我想到了一些选择,比如: 将所有记录(旧记录和新记录)存储在一个表中 创建两个表A和表B,一个(A)只保留当前记录,另一个(B)保留非当前记录。在本例中,我将使用新信息在B中插入,然后对A进行更新 与第一个选项相比,我更喜欢第二个选项,但我不确定第二个选项是否真的是解决方案,或者仅仅是一种奇特的方式,因为最后我存储

我有一个表a,其中存储了用户可以更新的信息,但由于用户的要求,我需要跟踪信息中的更改。 考虑到:

  • 此信息将在用户需要时显示
  • 信息可以随时更改,但不经常更改,比如说一年更改5次
我想到了一些选择,比如:

  • 将所有记录(旧记录和新记录)存储在一个表中
  • 创建两个表A和表B,一个(A)只保留当前记录,另一个(B)保留非当前记录。在本例中,我将使用新信息在B中插入,然后对A进行更新
与第一个选项相比,我更喜欢第二个选项,但我不确定第二个选项是否真的是解决方案,或者仅仅是一种奇特的方式,因为最后我存储了相同数量的数据,对吗

是否有人有其他选择,或者在开发时如何面对这种情况

多谢各位


Azu

我通常会选择后者,除非我有一个分区方法可以将所有当前记录保存在它们自己的分区集中

原因是,否则,当前记录和旧记录会混合在同一个数据块中,这会降低缓存的效率,因为通常不需要经常使用旧记录

如果使用前一种方法,我会标记记录的“当前”版本,以便通过索引轻松地找到它们

然而,这也会影响查询优化人员对预期基数的估计。如果它看到20%的行是“当前”行,5%的行在上个月有某个日期(last_transaction?),则可能会推断1%的当前行在上个月有日期,而实际数字可能高于20%


总的来说,如果历史记录作为正常应用程序活动的一部分很少需要,我会将它们放到一个专用的表中。

我通常会选择后者,除非我有一种分区方法可以将所有当前记录保留在它们自己的分区集中

原因是,否则,当前记录和旧记录会混合在同一个数据块中,这会降低缓存的效率,因为通常不需要经常使用旧记录

如果使用前一种方法,我会标记记录的“当前”版本,以便通过索引轻松地找到它们

然而,这也会影响查询优化人员对预期基数的估计。如果它看到20%的行是“当前”行,5%的行在上个月有某个日期(last_transaction?),则可能会推断1%的当前行在上个月有日期,而实际数字可能高于20%


总的来说,如果历史记录作为正常应用程序活动的一部分很少需要,我会将它们放到一个专用的表中。

我通常会选择后者,除非我有一种分区方法可以将所有当前记录保留在它们自己的分区集中

原因是,否则,当前记录和旧记录会混合在同一个数据块中,这会降低缓存的效率,因为通常不需要经常使用旧记录

如果使用前一种方法,我会标记记录的“当前”版本,以便通过索引轻松地找到它们

然而,这也会影响查询优化人员对预期基数的估计。如果它看到20%的行是“当前”行,5%的行在上个月有某个日期(last_transaction?),则可能会推断1%的当前行在上个月有日期,而实际数字可能高于20%


总的来说,如果历史记录作为正常应用程序活动的一部分很少需要,我会将它们放到一个专用的表中。

我通常会选择后者,除非我有一种分区方法可以将所有当前记录保留在它们自己的分区集中

原因是,否则,当前记录和旧记录会混合在同一个数据块中,这会降低缓存的效率,因为通常不需要经常使用旧记录

如果使用前一种方法,我会标记记录的“当前”版本,以便通过索引轻松地找到它们

然而,这也会影响查询优化人员对预期基数的估计。如果它看到20%的行是“当前”行,5%的行在上个月有某个日期(last_transaction?),则可能会推断1%的当前行在上个月有日期,而实际数字可能高于20%


总的来说,如果历史记录作为正常应用程序活动的一部分很少需要,我会将它们放到一个专用的表中。

您肯定不想使用当前指示符标志,因为这会极大地影响对行所代表的语义和理解。每一行应该代表世界上一个不同的实体。添加当前指标时,现在的每一行可能代表单个实体,或者可能代表该实体在一段时间内的特征的版本。查询此表现在变得更复杂,更容易出错

但在设计历史表之前,请检查DBMS是否提供了任何时间特性。例如,支持创建可以自动跟踪历史的时态表。现在还支持时态表。另一个选项是查看DBMS是否提供更改数据捕获选项,该选项可以配置为捕获每个更改并将其写入副本,在这里工作
create table Versions(
    ID        int not null,
    ModDate   date not null,
    ModUserID int not null,
    ...     ..., -- data fields
    constraint PK_Versions primary key( ID, ModDate ),
    constraint FK_Versions_Primary foreign key( ID )
        references Primary( ID ),
    constraint FK_Versions_User foreign key( ModUserID )
        references Users( ID )
);
select  *
from    Versions v
where   v.ModDate =(
        select  Max( v1.ModDate )
        from    Versions v1
        where   v1.ID = v.ID );
select  p.*, v.* -- You will want to expand these out
from    Primary p
join    Versions v
    on  v.ID = p.ID
    and v.ModDate =(
        select  Max( v1.ModDate )
        from    Versions v1
        where   v1.ID = v.ID );
select  *
from    Versions v
where   v.ModDate =(
        select  Max( v1.ModDate )
        from    Versions v1
        where   v1.ID = v.ID
            and v1.ModDate <= :DateOfInterest );