13

我需要每天更新一个非常大(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'

但是,这在我的服务器上需要将近 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
    
  2. 我听说我可以使用 ROWCOUNT 执行批处理 MERGE - 但我认为它对于 300M 行表来说不够快。

  3. 任何有用的 SQL 查询提示?

4

2 回答 2

11

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

查看下面查询的查询计划,我们可以说TABLE SCANTABLE1 和 finalMERGE占用了 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

因此,为了使用 MERGE,我们需要:

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

正如 Mark 提到的,您可以使用UPDATE语法和 useWHERE子句来缩小要合并的部分 - 这将给出相同的结果。也请避免索引TABLE1,因为这会导致额外的工作来重建索引MERGE

于 2011-05-17T11:26:00.377 回答
10

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

重新创建完整的表是大量的 IO 负载,更不用说它会占用大量的空间来临时存储两次表。

您是否需要执行 MERGE - 据我所知,一个简单的更新就足够了。例子:

UPDATE
    TABLE1
SET
    ColumnX = UTABLE.ColumnX
    ...
FROM
    TABLE1
INNER JOIN
    UTABLE ON TABLE1.record_id = UTABLE.record_id

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

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

于 2011-05-14T13:09:02.080 回答