SQL Server中非常大的表的更新或合并

Ser*_*lov 9 sql-server-2008 sql-update sql-merge

我需要每天更新一个非常大的(300M记录)和广泛的TABLE1.更新的源数据位于另一个表中UTABLE,该表是行的10%-25%TABLE1但是很窄.两个表都record_id作为主键.

目前,我正在TABLE1使用以下方法重新创建:

<!-- language: sql -->
    1) SELECT (required columns) INTO TMP_TABLE1 
    FROM TABLE1 T join UTABLE U on T.record_id=U.record_id  
    2) DROP TABLE TABLE1  
    3) sp_rename 'TMP_TABLE1', 'TABLE1'
Run Code Online (Sandbox Code Playgroud)

但是,我的服务器上需要将近40分钟(SQL Server为60GB的RAM).我希望获得50%的性能提升 - 我可以尝试其他选项吗?

  1. MERGE并且UPDATE- 类似下面的代码只适用于非常小的UTABLE表 - 在完整大小时,所有内容都会挂起:

    <!-- language: SQL -->
    MERGE TABLE1 as target  
    USING UTABLE as source  
    ON target.record_id = source.record_id   
      WHEN MATCHED THEN   
        UPDATE SET Target.columns=source.columns
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我听说我可以使用ROWCOUNT执行批量MERGE - 但我不认为它对于300M行表来说足够快.

  3. 任何SQL查询提示都有帮助吗?

Ser*_*lov 8

实际上我已经找到了这样一个查询的一般建议:使用SQL Merge或Update的想法非常聪明,但是当我们需要在一个大而宽的表(即240M)中更新许多记录(即75M)时,它会失败.

查看下面查询的查询计划,我们可以说TABLE SCANTABLE1和final 的查询计划MERGE占用了90%的时间.

MERGE TABLE1 as Target  
USING UTABLE as source  
ON Target.record_id = source.record_id   
WHEN MATCHED AND (condition) THEN   
    UPDATE SET Target.columns=source.columns
Run Code Online (Sandbox Code Playgroud)

所以为了使用MERGE,我们需要:

  1. 减少我们需要更新的行数并将此信息正确传递给SQL Server.这可以通过UTABLE缩小或指定condition要缩小待合并部分的附加内容来完成.
  2. 确保要合并的部分适合内存,否则查询运行速度会变慢.做TABLE1两次下降较少我真正的查询时间从11小时至40分钟.

正如Mark所提到的,你可以使用UPDATEsyntax和use WHERE子句来缩小要合并的部分 - 这将得到相同的结果.另外请避免索引,TABLE1因为这会导致额外的工作来重建索引期间MERGE


Mar*_*sen 7

首先,我会发现你的瓶颈在哪里 - 你的CPU是固定的还是空闲的?换句话说 - 您的IO子系统是否能够正确处理负载?

重新创建整个表是很多IO负载,更不用说它占用了大量空间,基本上暂时存储了两次表.

你需要执行一个MERGE - 我可以看到一个简单的更新就足够了.例:

UPDATE
    TABLE1
SET
    ColumnX = UTABLE.ColumnX
    ...
FROM
    TABLE1
INNER JOIN
    UTABLE ON TABLE1.record_id = UTABLE.record_id
Run Code Online (Sandbox Code Playgroud)

您可以使用ROWCOUNT批量更新,但这不会加快执行速度,它只会有助于减少整体锁定.

另外 - 你在桌子上有什么样的索引?在更新之前禁用索引可能会更快,然后从头开始重建它们(仅限非聚簇).