【问题标题】:SQL Server 2005 loading data from an external serverSQL Server 2005 从外部服务器加载数据
【发布时间】:2009-09-12 15:55:38
【问题描述】:

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

我的客户在他们的办公室有一台 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

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

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

【问题讨论】:

  • 这是一个建议,所以我将其作为评论:您是否尝试过 SQL 数据比较? (red-gate.com/products/SQL_Data_Compare/index.htm)
  • 转机时间可以接受多长时间?
  • 在您提供一些相关信息之前,没有人能够帮助您:1) 数据连接的实际吞吐量是多少?不是您的查询,而是连接?如果你不知道这一点,你只是随风吐痰。 2) 您的平均记录大小是多少,3) 每晚要传输的平均记录数,4) 源的表定义是什么,包括任何键和索引?一旦我们掌握了这些信息,那么某人就有机会为您提供帮助。
  • 郑重声明:完全有可能,甚至很可能,实际问题既不是网络延迟,也不是您网站上的插入时间,而是缺少索引(最好是聚集索引)在源表的 LastModified 列上,强制您的查询每晚重新扫描整个表。提供我上面指出的信息将更容易确定这三个中的哪一个是罪魁祸首,并就您可以采取的措施提出建议。

标签: sql sql-server sql-server-2005 tsql etl


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    听起来您正在寻找一种单向(仅限下载)同步。为了获得最佳可靠性,我会要求供应商 (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 notes 了解更多信息。

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

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 是的,网络延迟是问题之一,但由于成本限制,我的客户不会获得专用的租用线路 :-( 到目前为止的音量(在不同天运行测试后)似乎范围从 10-100 MB 尝试向供应商询问预定的导出,但也遇到了问题。
      • 听起来你的选择非常有限。唯一要建议的另一件事是在 SSIS 中试用您的查询并使用批量大小等,看看它是否有助于加快速度。由于网络是主要问题,如果没有到位级别的复制工具,您将无能为力,但是由于不允许复制日志传送,我猜您将无法尝试 Double Take 之类的东西。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

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

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

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

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

        那么,计算从一张大桌子转移需要多长时间。

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-08
          • 1970-01-01
          • 1970-01-01
          • 2019-11-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多