历史机制的最佳表现方法?

时间:2011-11-17 09:00:11

标签: sql-server performance

enter image description here

我们将通过触发器为数据库中的更改(图中的 DART )创建历史记录机制。

我们有600张桌子。

每个将被更改的记录 - 触发器会将已删除的记录插入 XXX


关于 XXX

选项1 :克隆“Dart”数据库中的每个表,现在每个表都有一个“姐妹表”

e.g。 : Table1Table1_History

问题:

  • 我们将有1200张桌子
  • 程序员可以通过处理错误的表来犯错误......

选项2 :制作数据库(图片中为DART_2005),历史记录表将在那里


选项3 :使用链接服务器存储将包含历史记录表的Db。


问题:

1)哪个选项提供最佳性能(我猜3不是 - 但它是1还是2还是相同?)

2)选项2是否像“链接服务器”一样(在查询中我们需要从两个数据库中选择......)

3)最佳做法是什么?

2 个答案:

答案 0 :(得分:1)

1和2将具有相似的性能;如果您当前受限于数据库服务器上的某些资源(例如磁盘IO),并且您可以使用非常快速的网络,则选项3 可能更快。

选项1将导致DART数据库的备份时间更长 - 这可能是一个问题。

一般来说,我相信如果您的应用程序域需要“历史”的概念,您应该将其构建为一流的功能。有几种方法 - 查看问题How to create a point in time architecture in MySQL中的链接。

同样,一般来说,我不喜欢使用触发器来满足这种要求。你的触发器必须非常简单 - 在这种情况下,使用它在历史表中创建的数据并不总是很容易 - 或者它必须是智能的,在这种情况下你的触发器会做很多工作,这可能会使你的数据库架构将来会更难。

答案 1 :(得分:1)

这三种方法都是可行的,并且根据您的网络速度具有相似的性能,但每个方法都会让您在拥有许多并发用户的系统上遇到很多麻烦。

由于您将在一个事务中使用非常不同的访问模式插入/更新多个表(源表是随机的,历史表是顺序的),您最终会遇到阻塞和/或死锁。

如果无法更改现有表架构

如果您希望有一个由数据库驱动的历史记录系统,那么您将对历史记录更新进行排队,以防止阻塞问题。

  • 触发更新表格的触发器
  • 触发器会将包含插入/删除的表格信息的消息提交给SQL Server Service Broker队列
  • 激活存储过程可以从队列中提取信息并将其写入相应的历史记录表
  • 失败时,会向“错误队列”发送新消息,其中重试机制可以重新提交到原始队列(确保在消息中包含重试计数器)

这样,您的历史记录更新将是非阻止的,不会丢失。

注意:使用SQL Server Service代理时,请确保完全理解“Poison message”概念。

如果可以更改现有的表架构

如果这是一个选项,我建议使用“记录版本控制”系统,每次更新都会创建一个新记录&您的应用程序将正确查询最新版本的数据。为了确保正常的性能,可以将表分区为将最新版本的数据保留在分区中,将旧版本保留在归档分区中。 (我通常有一个字段end_dateexpiration_date,对于当前有效的记录,该字段设置为9999/12/31。)

这种方法当然需要在您的数据模型和现有应用程序中进行大量代码更改,这可能不太具成本效益。