[英]SQL server data backup/warehouse
我被要求为数据库中的某些表做快照,因此将来我们可以清楚地了解过去任何一天的情况。 可以说,其中一个表如下所示:
GKEY Time_in Time_out Category Commodity
1001 2014-05-01 10:50 NULL EXPORT Apples
1002 2014-05-02 11:23 2014-05-20 12:05 IMPORT Bananas
1003 2014-05-05 11:23 NULL STORAGE Null
制作快照的简单方法是使用另一列SNAPSHOT_TAKEN(Datetime)创建表的副本,并使用INSERT语句填充它
INSERT INTO UNITS_snapshot (SNAPSHOT_TAKEN, GKEY,Time_in, Time_out, Category, Commodity)
SELECT getdate() as SNAPSHOT_TAKEN, * FROM UNITS
好的,它工作正常,但是很快就会使目标表变得很大,尤其是如果我想经常运行此查询时。 更好的解决方案是检查当前活动表和最新快照之间的更改并将其记录下来,从而忽略所有未更改的内容。 是否有编写这种查询的简单方法?
编辑:“转发增量”的可能解决方案(假设没有从原始表中删除)
INSERT INTO UNITS_snapshot
SELECT getdate() as SNAP_DATE,
r.* -- Here goes all data from from the original table
CASE when b.gkey is null then 'I' else 'U' END AS change_type
FROM UNITS r left outer join UNITS_snapshot b
WHERE (r.time_in <>b.time_in or r.time_out<>b.time_out or r.category<>b.category or r.commodity<>b.commodity or b.gkey is null)
and (b.snap_date =
(SELECT max (b.snap_date) from UNITS_snapshot b right outer join UNITS r
on r.gkey=b.gkey) or b.snap_date is null)
假设:原始表中的任何值都不会删除。 也许WHERE中的每个字段也应为COALESCE(xxx,''),以避免将空值与设置的值进行比较。
Dan Bracuk和ITroubs都发表了很好的评论。
您提出的第一个解决方案非常简单。 您可以使用简单的查询来构建快照,也可以通过仅过滤SNAPSHOT_TAKEN列来查询快照并使用非常简单的查询来重建一天的快照。
如果您只有数千条记录,那么我会选择这一条,而不必担心它的规模会越来越大。
这与解决方案1基本相同,但是随着时间的推移仅保留一些快照...以避免快照DB随时间无限增长。
最简单的方法就是保存最近N天的快照,也许是一两个月的数据。 一种更复杂的方法是保持快照的密度取决于年龄……因此,例如,您可以拥有上个月的每一天,加上过去3个月的每个星期日,再加上3个月的每个月底去年等等
此解决方案要求您开发一个过程来处理不再需要的快照删除。 它不像在查询中使用getdate()那样简单。 但是,您可以在空间和历史信息之间获得良好的平衡。 您只需要平衡一个好的快照保留策略即可满足您的需求。
建立任何类型的增量是一个复杂得多的过程。
通过存储初始快照(好像当天已插入所有行),然后在以下快照上,仅存储有关快照(N)和快照(N-1)之间的差异的信息,即可构建前向增量。 这是通过分析每一行并仅存储数据(如果该行是新行,更新行或删除行)来完成的。 如果主表随时间变化不大,则可以节省很多空间,因为没有信息存储未更改的行。
显然,要处理增量,您现在需要2个额外的列,而不仅仅是一个:
主要的复杂性源于识别行的必要性(通常通过主键),以便计算在2个快照之间是否已插入,更新,删除了任何单独的行……或以上都不是。
其他复杂性来自读取快照数据库和构建最新(或任何其他)快照。 这是必要的,因为表中仅存在行差异,因此不能仅通过按snapshot_taken进行筛选来选择一天的快照。
在SQL中这并不容易。 对于每一行,您必须只考虑最终版本...带有MAX snapshot_taken的那是<=要构建快照的日期。 如果是插入或更新,则保留该行的数据,否则(如果是删除),则将其忽略。
要构建快照增量(N),必须首先从快照数据库构建最新的快照(N-1)。 然后,您必须通过主键或行标识比较两个快照,并计算更改类型(I / U / D),并将更改插入快照数据库中。
请注意,如果不先合并旧快照数据就无法删除它。 这是因为所有快照都是根据最早的初始快照和所有后续的差异数据计算得出的。 如果要删除一年的旧快照,则必须将旧的初始快照和一年中的所有变体合并到新的初始快照中。
这与解决方案3非常相似,但更为复杂。
通过存储最终快照,然后在以下快照上,仅存储有关快照(N-1)和快照(N)之间差异的信息,可以构建后向增量。
优点是,通过快照数据库上的简单选择,始终可以随时获得最新快照。 要检索较旧的快照时,仅需要合并差异数据。 将此与正向增量进行比较,在正向增量中,除非真正对第一个快照真正感兴趣,否则始终需要根据差异数据重建快照。
另一个优点(与解决方案3相比)是,您可以通过删除比特定快照更早的差异数据来删除较早的快照。 您可以轻松完成此操作,因为快照是根据最终快照而不是初始快照计算得出的。
缺点是逻辑模糊。 差异数据是向后计算的。 值必须存储在(U)pdate和(D)elete变量上,但在I变量上是不必要的。 向后看,如果找到的第一个变体是(I)nsert,则必须忽略行。 可行,但有点棘手。
如果主表有许多列,或者有许多长文本列或varchar列,并且其中只有一堆被更新,那么只存储列变体而不是行变体是有意义的。
这可以通过使用具有以下结构的表来完成:
可以按行增量向前或向后计算差异。
我已经看到了这一点,但我真的建议不要这样做。 有太多的缺点和增加的复杂性。
值是文本或varchar,如果您有数字,布尔值或日期/时间值,则存在类型转换问题要解决...并且,如果您有很多这些,很可能您不会将其另存为您认为自己的空间很大。
重建任何快照都是地狱。 总共...对这种类型的表进行的任何操作实际上都需要大量有关主表结构的知识。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.