我需要快速实现一个只读数据库,其中包含从两个结构相同的实时数据库中提取的数据。
实时dbs实际上是来自Dynamics会计系统的公司dbs所以我很高兴任何Dynamics特定的建议,但这主要是一个SQL问题。从Great Plains被微软收购之前,这是一个相当古老的Dynamics版本。这是在SQL Server 2000上。
我们有访问Dynamics数据的报告和应用程序。这些应用程序旨在查看一个公司数据库。现在我们需要添加另一个。大多数这些报告和应用都可以看到组合数据。他们并不真正关心订单或发票存在于哪家公司。他们只关注少数几个表。
在我看来,最简单的解决方案是使用组合数据创建仅报告数据库。最好是,我们需要一种有效的方法来更新此数据库,每天更改几次。
我是开发人员,不是数据库专家,但这是我的计划:
使用与live dbs相同的表结构创建最初所需表的组合报告数据库。
所有Dynamics表似乎都有一个名为DEX_ROW_ID的int标识列。我不确定它用于什么,(它没有索引),但这似乎是唯一标识行的通用方法。在报告db上,我将其更改为普通int(不是标识)。我将在所有dbs中的DEX_ROW_ID上创建一个唯一索引。
Dynamics没有时间戳,因此我将向live dbs中的表添加timestamp列,并在报告db中添加相应的二进制(8)列。我假设并希望Dynamics不会被额外的索引和列所打扰。
将int CompanyId列添加到报告db表,并将其添加到任何唯一索引的末尾。即使没有它,大多数数据也将是自然独特的。即两个实时dbs的订单和发票号码等不同。我们可能需要对应用程序进行一些小的更改,但除了将它们指向新的报告数据库之外,我不希望做太多其他事情。
假设我的报告数据库名为Reports,实时dbs是Live1和Live2,时间戳列称为TS,所有db都在同一台服务器上......这是我第一次尝试更新脚本以复制一个在Live1中将MyTable称为报告数据库。
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 db做同样的事情。对Reports中的每个表重复此操作。我知道我应该使用参数@CompanyId而不是文字,但我不能为实时数据库名称这样做,我可能会使用C#程序或其他东西动态生成这些名称。
我正在寻找关于我在这里所做的任何建议,建议或批评。我知道它不会是原子的。当这个脚本运行时,实时数据库上可能会发生一些事情。我想我们可以忍受这一点。我们可能会在每晚或每周都做一整份,因为现场dbs什么也没发生。
我们需要优雅表现而不是优雅或完美。一些初始测试有第一个查询,TS比较大约30秒运行最大的表,所以我很乐观这是可行的,但我也想知道我是否遗漏了一些明显或没有看到的东西森林为树木。
我们真的不想处理报告数据库上的日志文件。我们可以将其设置为简单恢复模型并忘记日志吗?
由于
答案 0 :(得分:1)
我认为这里有几个未解决的问题。
您是否需要近乎实时的报告?或者这种报告可以与每日更新一起生活吗?但假设您需要最新的数据。
您是否考虑过直接查询数据库并动态合并每个报告的数据?您将不得不进行大量报告,以复制设计,创建和支持实时合并复制数据库的工作量。
针对生产数据库的任何单个查询都不能接受30秒(恕我直言)。花费这么长时间可能存在任何与调整相关的原因,但这至少意味着您将需要严格的专业SQL Server优化资源(即人员)。如果这对于报告查询来说是一个问题,那么查询维护单独的数据库以进行报告就不是好事。
考虑到如果您需要整合到单个数据库,则值得考虑是否应该将其设置为OLAP数据库而不是镜像。镜子将更快更容易,但从长远来看,OLAP将更加灵活和强大;从一开始就全力以赴。
答案 1 :(得分:0)
我要做的最后一件事是编写自定义更新脚本。首先尝试这些防弹方法:
这可能看起来像蛮力。但是,由于您正在复制一个2000年代的数据库,因此对于今天的硬件来说,暴力破解不是问题。作为一个额外的优点,系统管理员可以支持这些方法,而不是开发人员。
方法1还具有作为备份验证的附加优势。 :)