0

有一个具有以下设置和要求的新项目:-

我的客户在他们的办公室有一台 MSSQL 2005 服务器 (A)。他们的供应商在世界的另一个地方有一个 MSSQL 2005 服务器 (B),其中包含实时事务数据。我的客户希望在非办公时间每天将数据从 (B) 加载到 (A)。他们可以访问(B)的数据读取器,但仅此而已,供应商将不会进行复制、日志传送等,我的客户全权负责获取他们自己的数据,以便他们可以运行自己的报告/多维数据集。

我使用的脚本如下使用分布式TSQL和链接服务器到(B): -

DECLARE @sqlCommand        VARCHAR(2000)
DECLARE @LastProcessedDate DATETIME

-- run the following code for Table 1 to Table XX

SELECT @LastProcessedDate = LastProcessedDate 
  FROM [ProcessControl] 
 WHERE TableName = 'table_1'

SET @sqlCommand = 'INSERT INTO Table1 
                   SELECT * 
                     FROM OPENQUERY(VendorsLinkedServerName, 
                          ''SELECT * 
                              FROM Table1 
                             WHERE LastModified >= '''' + @LastProcessedDate + '''')'

EXEC @sqlCommand

我为 1 个全天的数据对 10 个最大的表进行了初步试验,花了 1 个小时,这太长了。同样对于测试,我已经删除了除了表的主键(包括 1-4 BIGINT 列)之外的所有索引和约束。关于如何加快加载时间或加载数据的任何建议?

编辑:只是补充一下,如果你想知道为什么选择语句是这样写的,在上面的例子中(A)中的表1在一个ETL数据库中,随后将比较数据以确定实际中的插入/更新/删除(A) 中的报告数据库

4

5 回答 5

1

不幸的是,我猜最大的减速只是网络延迟,对此您无能为力。

不过,我确实有一个想法。尝试将 ORDER BY 子句添加到与目标表的主键(聚集索引)匹配的 SELECT 语句中。这可以减少插入期间重新排序表格的需要。

另外,那里有多少张桌子,你有多少时间?如果您在一小时内完成了最大的 10 个,您可能会发现有一个 90/10 规则在起作用,这样所有其他桌子加起来仍然比这 10 个花费的时间更少。

于 2009-09-12T16:29:50.600 回答
1

听起来您正在寻找一种单向(仅下载)同步。为了获得最佳可靠性,我会要求供应商 (B) 添加一个 ROWVERSION 列,它比 DateTime 或 DateTimeOffset 安全一点。

至于你的查询,我做了如下的事情:

INSERT INTO dbo.Table1
(
    Field1,
    Field2,
    Field3
)
SELECT
    T1.Field1,
    T1.Field2,
    T1.Field3
FROM [LinkedServer].[DatabaseName].[dbo].[Table1] T1
WHERE T1.Version > @LastAnchor

如果您的模式相同,则可以通过 CreatedVersion 和 UpdatedVersion 跳过整个 ETL 阶段,如果需要,可以使用 Tombstone 行进行删除。Sync Framework为您简化了很多工作,尽管您可以使用这些概念相对轻松地烘焙自己的概念。规则如下:

-- get inserts in dependency order
INSERT INTO ...
SELECT ...
FROM ...
WHERE CreatedVersion > @LastAnchor
-- get updates in dependency order
UPDATE [dbo].[Table1]
SET ...
FROM [LinkedServer].[DatabaseName].[dbo].[Table1] T1
WHERE [dbo].[Table1].[PK] = T1.[PK]
    AND T1.CreatedVersion <= @LastAnchor
    AND T1.UpdatedVersion > @LastAnchor
-- get deletes (if you need them)
DELETE T
FROM [dbo].[Table1] T
JOIN [LinkedServer].[DatabaseName].[dbo].[Table1_Tombstone] T1
    ON T.[PK] = T1.[PK]
    AND T1.DeletedVersion > @LastAnchor

为了使所有这些查询都能正常执行,应为 CreatedVersion、UpdatedVersion 和 DeletedVersion 列编制索引。

以上所有逻辑都适用于 DateTime 或 RowVersion,只是 RowVersion 更准确,并且 2005 SP2 解决了正在进行的事务周围的一些问题。基本上在 SQL 2005 SP2 和 SQL 2008 中,您将最大锚点设置为 MIN_ ACTIVE_ROWVERSION() - 1 并查询介于两者之间的内容。查找MSDN 说明以获取有关原因的更多信息。

与某些人不同,我强烈建议不要将 UpdatedVersion 设为聚集索引,因为这将涉及在更新完成时不断重新排序页面上的数据,如果您向供应商推荐,您将看起来像个傻瓜。

使用 Sync Framework 的一个优点是您可以使用 WCF 进行数据调用并定期进行较小的同步,而不是在每天结束时进行大量同步。这将要求供应商提供或至少托管提供数据库访问的 WCF 服务。如果您愿意,您仍然可以使用带有同步框架的链接服务器,同时仍然支持更频繁地完成较小的同步。

于 2009-09-13T15:00:04.247 回答
0

性能是由于网络延迟而不是您采用的方法吗?你正在处理什么样的卷等等。

我注意到他们不会进行复制或日志传送,但你能说服他们做一些计划的批量导出,这些导出可以被压缩并发送到另一端的自动例程以进行批量插入?

于 2009-09-12T16:09:12.493 回答
0

在本地尝试查询(或尝试让他们在本地运行查询)并查看需要多长时间。正如克里斯指出的那样,这可能是网络延迟。您是否有能力在供应商方面推出 SSIS 包?如果是这样,您可以提取和压缩数据,通过 FTP 任务或其他机制传送它,然后解压缩/插入数据。

于 2009-09-12T16:20:12.383 回答
0

正如 Chris W 所建议的那样,您可能需要进行一些测试以确定减速的位置。

例如,进行查询并将信息转储到文件中,并对其计时。

只需运行查询,忽略您获得的任何数据,看看传输数据需要多长时间。

然后您就知道转移的时间以及如果您将数据库从循环中取出会发生什么。

然后,您可以确定最佳行动方案。

您可能还想做很多单独的查询。

所以,时间从一张大桌子转移需要多长时间。

然后对大表进行 5 次查询,看看会发生什么。

如果可能的话,您可能想看看是否可以同时建立多个连接,并快速 d/l 数据,将其转储到空数据库中,然后通过从本地副本复制到数据库来为索引付出代价。

但是,除非您有一些数字来了解操作需要多长时间,否则所有这些都是毫无意义的。

于 2009-09-12T16:22:34.437 回答