将来自不同表的数据聚合成一个是不好的做法吗?

jre*_*121 12 trigger sql-server ssrs sql-server-2008-r2

背景

我为大型健康记录数据库编写了很多大型报告,并且通常维护大型健康记录数据库(编写 SP、函数、作业等)。原始模式和使用它的软件来自不同的供应商,因此我无法在结构上对其进行太多更改。有许多记录需要跟踪,例如实验室、程序、疫苗等,它们分散在几十个表中,其中许多表臃肿且索引不佳(我已经能够稍微解决这个问题)。

问题

问题是,因为我们对数据库几乎没有控制,而且由于它可以从任何给定的更新或补丁中更改,这使得编写和维护这些报告变得困难和乏味——尤其是当存在大量重叠时。只需要一个补丁,我就不得不重写十多份报告的大部分内容。此外,随着连接、嵌套选择和应用堆积,查询很快变得模糊和缓慢。

我的“解决方案”

我的计划是将所有这些记录写入一个“全能”表,并在原始表上写入触发器以维护该聚合表中的记录。当然,我需要确保我的触发器在更新后完好无损,但从可维护性的角度来看,这会容易得多,只需引用数据。

表会又细又长,只存储所需的数据,如下所示:

CREATE TABLE dbo.HCM_Event_Log (
    id INT IDENTITY,
    type_id INT NULL,
    orig_id VARCHAR(36) NULL,
    patient_id UNIQUEIDENTIFIER NOT NULL,
    visit_id UNIQUEIDENTIFIER NULL,
    lookup_id VARCHAR(50) NULL,
    status VARCHAR(15) NULL,
    ordered_datetime DATETIME NULL,
    completed_datetime DATETIME NULL,
    CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)
Run Code Online (Sandbox Code Playgroud)

然后我会有各种关系表,比如 type_id 和项目分组。

我开始重新猜测这个想法,因为其中有几个表被写入了相当多的内容,我要编写的 SP 和报告也会引用很多数据。所以我担心这个表会成为具有如此多 I/O 的记录锁定和性能噩梦。

我的问题

是坏主意还是好主意?我意识到 SQL Server(2008 r2 标准版 BTW)和“有时”规则中的每种情况都不同,但我真的只是在寻找一般建议。

我开始考虑使用服务代理,但我只会执行简单的更新/插入(请参阅已接受答案的替代方法)。在许多情况下,数据需要是实时的,因此使用备份 DB 不会真正起作用。性能对我们来说已经是一个问题,但其中大部分与硬件相关,很快就会得到解决。

Vla*_*nov 8

如果我理解正确的话,

  • 你有一个大型的第三方系统,
  • 你没有太多的控制权,
  • 你制作复杂的报告,直接从这个第三方数据库读取数据,
  • 您的查询取决于第三方数据库的内部结构。

我会这样处理它:

  • 建立我自己的独立数据库,我可以完全控制它。
  • 设置一个同步过程,从第三方数据库的相关表和列中读取数据,并将数据插入/更新到我的数据库中。
  • 根据我的数据库的稳定结构开发我的复杂报告。

在这种情况下,您可以微调数据库的结构和索引以提高报告的性能,而不会影响第三方系统。除非原始数据结构发生巨大变化,否则如果第三方数据库发生变化,您对报表的查询逻辑不会发生变化。您只需调整同步过程。

同步过程实际上是转换过程 - 您将数据从第三方数据库转换为您需要的结构。此转换过程的一部分可能是修复原始第三方数据库可能存在的任何规范化问题。只有这部分系统需要知道和依赖第三方系统的内部结构。您的主要报告和主要查询将仅取决于您的数据库。

所以,重点是 - 分离和限制依赖于第三方系统内部的系统部分。

更新

关于实时性要求。顺便说一句,我一直认为“实时”的定义是“保证响应时间”,而不是“一些小的响应时间”。当然,这取决于您的应用程序。在我的实践中,如果我在检测到更改后的一分钟内同步两个数据库就足够了。如果用户在屏幕上看到报告并且一些基础数据发生了变化,则必须以某种方式重新运行报告以反映这种变化。您可以轮询更改或收听某些事件/消息,但仍必须再次执行报告查询以显示最新更改。

您已经打算编写触发器来捕获原始表中的更改并将这些更改写入一个通用表。因此,按照您的意图捕获更改,但将它们写入正确规范化的表,而不是单个表。

因此,这是一种极端情况 - 第三方数据结构到您的内部数据结构的转换是在触发INSERT/UPDATE/DELETE第三方表的触发器中执行的。这可能很棘手。触发器的代码取决于两个系统的内部结构。如果转换不是微不足道的,它可能会延迟原始INSERT/UPDATE/DELETE到它们的失败点。如果您的触发器中存在错误,它可能会影响原始事务直至其失败。如果第三方系统更改可能会破坏您的触发器,从而导致第三方系统的交易失败。

不太极端的情况。为了使触发器的代码更简单且不易出错,将所有捕获的更改写入某些暂存/审计/差异表,设置一些标志/发送一条消息,表明有更改未决并启动将进行的主要转换过程通过这些中间表并进行转换。这里的主要事情是潜在的繁重转换过程应该发生在原始交易的范围之外。

乍一看,它看起来很像您在问题中的原始建议。但是,不同之处在于:捕获所有表仅临时保存数据;数据量很小 - 只是发生了变化;它不必是一张桌子;最终,数据将存储在单独的正确规范化的永久表中,您可以完全控制这些表,这些表独立于第三方系统,您可以针对您的查询进行调整。