sql - 如何加快聚集列的大规模更新?

标签 sql sql-server performance indexing

我有一个非常大的表:20 多万行,我需要更新其中的 5% - 或 100 万行。

不幸的是,我正在更新用作聚集索引的 (int) 列。

我的问题是:
更新这些行的最快方法是什么?


我试过直接更新行:

update t1
set t1.groupId = t2.groupId
from
    table t1
join newtable t2 on t1.email = t2.email

但这需要太长时间(我在 3 小时后停止了它)

我认为这是因为每次更新都会移动整行(有 2 个日期时间、2 个 varchars 和 2 个整数)。

如果我先删除聚集索引,然后进行更新,然后重新创建聚集索引会怎样?那会更快吗?

注意:我在电子邮件上有一个非聚集索引,以防有人认为查询的选择部分很慢。它不是。

最佳答案

这是我所做的(而且速度要快得多):

  • 我删除了聚集索引。
  • 我也删除了外键
    引用(另外两个 int
    列)。
  • 我运行了更新语句
  • 我重新创建了索引,这比预期的要快。 (这是我首先问 SO 的最初原因)。

  • 这使整个过程缩短到几秒钟。 是的,大约 15 秒内约 100 万行。

    第二步至关重要,因为外键强制更新对相关表执行某种假脱机操作,每个表也有大量行。

    由于这些外键查找,物理读取的数量增加了两倍。

    我不确定为什么 SQL Server 需要这样做,但我的猜测是,即使我没有更新该列但我正在移动整行(簇列更新),它仍然会执行完整性检查。

    作为旁注,我还尝试分批运行更新:
    update top(1000) t1
    set t1.groupId = t2.groupId
    from
        table t1
    join newtable t2 on t1.email = t2.email
    

    这很好(并且每批似乎可以扩展到大约 10K),但每批仍然需要 1-2 分钟。

    总之,我了解到对于批量更新,临时删除索引非常有帮助。

    关于sql - 如何加快聚集列的大规模更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1016631/

    相关文章:

    c++ - 产品/消费者——什么是最佳信号模式

    Python:处理平均时间,第一个/第二个慢得多

    SQL - 使用 Group By 时以逗号分隔数据

    mysql - 在单个查询 Mysql 中获取相应 ID 的计数

    mysql - SQL:INSERT + SET - 标准的还是特定于 MySQL 的?

    java - 在 JPA 上选择 DISTINCT

    sql-server - SQL Server : If @variable is null set @variable = x

    .net - 为什么 ToUpper 会导致 Entity Framework 5.0 切换到 Unicode?

    尽管更新了统计数据,SQL Server 2016 的查询计划估计仍然不正确

    C# - 重载不同类型的方法是否比在单个方法中使用类型检查更高效?