【问题标题】:Best performance approach to history mechanism?历史机制的最佳性能方法?
【发布时间】:2011-11-17 18:19:44
【问题描述】:

我们将通过触发器为我们在 DB 中的更改(图中的DART)创建历史机制。

我们有 600 张桌子。

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


关于XXX

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

例如: Table1 将有 Table1_History

问题:

  • 我们将有 1200 张桌子
  • 程序员可能会因为处理错误的表而犯错...

选项 2:创建一个数据库(图中的 DART_2005),历史记录表就会在那里


选项 3:使用 linked 服务器来存储包含历史表的 Db。


问题:

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

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

3) 最佳实践方法是什么?

【问题讨论】:

  • 你能提供一些关于这个系统的使用模式的信息吗? (批处理/报告,oltp?)

标签: sql-server performance


【解决方案1】:

所有三种方法都是可行的,并且根据您的网络速度具有相似的性能,但是在具有许多并发用户的系统上,每一种方法都会让您非常头疼。

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

如果无法更改现有表架构

如果您希望建立一个由数据库驱动的历史系统,理想情况下,您可以将历史更新排队,以防止出现阻塞问题。

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

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

注意:使用 SQL Server 服务代理时,请确保您完全理解“毒消息”的概念。

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

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

这种方法当然需要对数据模型和现有应用程序进行大量代码更改,这可能不是很划算。

【讨论】:

    【解决方案2】:

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

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

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

    再说一次,总的来说,我不喜欢使用触发器来满足这种需求。您的触发器要么必须非常简单——在这种情况下,使用它在历史表中创建的数据并不总是那么容易——或者它必须很聪明,在这种情况下,你的触发器会做很多工作,这可能会使你的数据库模式在未来更难。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-24
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      • 2018-06-16
      • 2011-02-07
      • 2012-12-02
      • 2012-09-10
      相关资源
      最近更新 更多