0

我需要快速实现一个只读数据库,其中包含从两个结构相同的实时数据库中提取的数据。

实时数据库实际上是来自 Dynamics 会计系统的公司数据库,所以我很高兴有任何 Dynamics 特定的建议,但这主要是一个 SQL 问题。这是微软收购 Great Plains 之前相当老的 Dynamics 版本。这是在 SQL Server 2000 上。

我们有访问动态数据的报告和应用程序。这些应用程序旨在查看一个公司数据库。现在我们需要添加另一个。这些报告和应用程序中的大多数都可以看到组合数据。他们并不真正关心订单或发票存在于哪家公司。他们只查看少数表格。

在我看来,最简单的解决方案是创建一个仅包含合并数据的报告数据库。最好,我们需要一种有效的方法来每天多次更新这个数据库。

我是开发人员,不是数据库专家,但这是我的计划:

最初使用与实时数据库相同的表结构创建具有所需表的组合报告数据库。

所有 Dynamics 表似乎都有一个名为 DEX_ROW_ID 的 int 标识列。我不确定它的用途,(它没有被索引)但这似乎是唯一标识行的明显通用方法。在报告数据库上,我会将其更改为正常的 int(不是身份)。我将在所有数据库中的 DEX_ROW_ID 上创建一个唯一索引。

Dynamics 没有时间戳,因此我将在实时数据库中的表中添加时间戳列,并在报告数据库中添加相应的 binary(8) 列。我假设并希望 Dynamics 不会因额外的索引和列而感到不安。

将 int CompanyId 列添加到报告数据库表中,并将其添加到任何唯一索引的末尾。即使没有它,大多数数据自然也是独一无二的。即,两个实时数据库的订单和发票号码等将不同。我们可能需要对应用程序进行一些小的更改,但除了将它们指向新的报告数据库之外,我不希望做太多事情。

假设我的报告数据库称为 Reports,实时数据库是 Live1 和 Live2,时间戳列称为 TS,所有数据库都在同一台服务器上……这是我第一次尝试更新脚本,用于在一个名为 MyTable 的表中复制更改在 Live1 到报告数据库。

USE Reports

CREATE TABLE #Changes
(
ReportId int,
LiveId int
)

/* Collect in a temp table the ids or rows which have been deleted or changed
in the live db L.DEX_ROW_ID will be null if the row has been deleted */

INSERT INTO #Changes
SELECT R.DEX_ROW_ID, L.DEX_ROW_ID
FROM MyTable R LEFT OUTER JOIN Live1.dbo.MyTable L ON L.DEX_ROW_ID = R.DEX_ROW_ID
WHERE R.CompanyId = 1 AND L.DEX_ROW_ID IS NULL OR L.TS <> R.TS

/* Delete rows that have been deleted or changed on the live db 
I wonder if using join syntax would run better than the subquery. */
DELETE FROM MyTable
WHERE CompanyId = 1 AND DEX_ROW_ID IN (SELECT ReportId FROM #Changes)

/* Recopy rows that have changed in the live db */
INSERT INTO MyTable
SELECT 1 AS CompanyId, * FROM Live1.dbo.MyTable L
WHERE L.DEX_ROW_ID IN (SELECT ReportId FROM #Changes WHERE LiveId IS NOT NULL)

/* Copy the rows that are new in the live db */
INSERT INTO MyTable
SELECT 1 AS CompanyId, * FROM Live1.dbo.MyTable
WHERE DEX_ROW_ID > (SELECT MAX(DEX_ROW_ID) FROM MyTable WHERE CompanyId = 1)

然后对 Live2 数据库执行相同的操作。对报告中的每个表重复此操作。我知道我应该使用参数@CompanyId 而不是文字,但我不能为实时数据库名称这样做,有些我可能会使用 C# 程序或其他东西动态生成这些名称。

我正在寻找任何关于我在这里所做的事情的建议、建议或批评。我知道它不会是原子的。此脚本运行时,实时数据库上可能会发生一些事情。我认为我们可以忍受这一点。当实时数据库上没有发生任何事情时,我们可能会每晚或每周进行一次完整复制。

我们需要注重性能而不是优雅或完美。一些初始测试有第一个查询,其中最大表的 TS 比较运行时间约为 30 秒,所以我很乐观这会起作用,但我也想知道我是否遗漏了一些明显的东西或没有看到以树为林。

我们真的不想处理报告数据库上的日志文件。我们可以将其设置为简单的恢复模式而忘记日志吗?

谢谢

4

2 回答 2

1

我认为这里有几个悬而未决的问题。

  1. 您是否需要这些报告接近实时?或者这种报告可以与每日更新一起使用?但是假设您需要最新的数据。

  2. 您是否考虑过直接查询数据库并即时合并每个报告的数据?您必须进行大量报告以重复设计、创建和支持实时合并复制数据库的工作。

  3. 对于针对生产数据库的任何单个查询,30 秒(恕我直言)是不可接受的。花费这么长时间可能有许多与调优相关的原因,但这至少意味着您将需要认真的专业 SQL Server 优化资源(即人员)。如果这对于报告查询来说是一个问题,那么查询维护一个单独的数据库用于报告并不是一个好兆头。

  4. 回想一下,如果您需要整合到单个数据库,那么值得考虑是否应该将其设为 OLAP 数据库而不是镜像。镜像会更快更容易,但从长远来看,OLAP 会更加灵活和强大;从头开始可能会很好。

于 2009-05-10T19:28:36.803 回答
0

我想做的最后一件事是编写自定义更新脚本。首先尝试这些防弹方法:

  1. 希望您的生产数据库已备份。每晚将这些备份还原到报告服务器。您可以使用RESTORE 命令自动恢复,该命令将使用网络服务器上的文件。
  2. 使用SQL Server 复制将数据从实时服务器推送到后端。
  3. 每晚安排一个 DTS 包以导入整个生产数据库。

这似乎是蛮力。但是,由于您要复制 2000 年的数据库,因此对于当今的硬件而言,蛮力不会成为问题。作为一个额外的优势,这些方法可以由系统管理员而不是开发人员来支持。

方法 1 具有作为备份验证的附加优势。:)

于 2009-05-10T19:14:28.107 回答