【问题标题】:is there ANY way I can improve performance on this simple query?有什么方法可以提高这个简单查询的性能吗?
【发布时间】:2016-05-05 00:12:03
【问题描述】:

我想不出加快速度的方法。它正在执行表扫描,但我不得不这样做,因为我需要更新所有记录...

问题是这个表有数百万条记录......大约有 3000 万条。

这大约需要 50 分钟才能运行。有人对我如何改进有任何提示吗?

  update  A
  set     A.product_dollar_amt = round(A.product_dollar_amt, 2),
          A.product_local_amt = round(A.product_local_amt, 2),
          A.product_trans_amt = round(A.product_trans_amt, 2)
  from    dbo.table A

该表目前是一个堆(没有聚集索引),因为它没有在其他任何地方使用...不确定创建聚集索引是否会改善这里的任何事情。

【问题讨论】:

  • 批量更新怎么样?
  • 那会有什么不同呢?
  • 您可以使用 sp_WhoIsActive 监控查询,看看是否有任何异常等待发生。您还可以将此结果加载到 different 表中,然后将其重命名(或将其移动到不同的模式。然后更改似乎是即时的,但您需要存储两个完整的表3000 万条记录。
  • 添加索引只会减慢更新速度
  • 我不禁想知道这是否是一次性查询。如果是这样,那么需要多长时间并不重要,只需通过一次即可。如果不是,我不禁想知道为什么需要多次运行...相反,验证输入(并将字段设置为仅接受您实际想要的内容 - 例如,删除执行要求此更新(如果允许)。

标签: sql sql-server performance


【解决方案1】:

这里有三个选项。

Randy提到的第一个就是分批做工作。

第二种方法是将结果转储到临时表中并重新创建原始表:

select . . . , 
       product_dollar_amt = round(A.product_dollar_amt, 2),
       product_local_amt = round(A.product_local_amt, 2),
       product_trans_amt = round(A.product_trans_amt, 2)
into a_temp
from a;

drop a;

sp_rename 'a_temp', 'a';

注意:这不能保证更快,但因为记录插入比记录更新更快,所以通常是这样。此外,您还需要重建索引和触发器。

最后,有一个“不更新”的解决方案:改为创建派生值:

sp_rename 'A.product_dollar_amt', '_product_dollar_amount', 'COLUMN';
sp_rename 'A.product_local_amt', '_product_local_amt', 'COLUMN';
sp_rename 'A.product_trans_amt', '_product_trans_amt', 'COLUMN';

然后将列添加回公式:

alter table A add product_dollar_amt as (round(product_dollar_amt, 2));
alter table A add product_local_amt = round(product_local_amt, 2);
alter table A add product_trans_amt = round(product_trans_amt, 2);

【讨论】:

    【解决方案2】:

    你在这里真的没有任何选择。您正在更新每一行,这将需要尽可能长的时间。我可以告诉你,在单个事务中更新 30M 行并不是一个好主意。您可以轻松地炸毁您的事务日志。如果此表被其他用户使用,您可能会将他们全部锁定,直到整个表被更新。小批量更新此表会更好。整体性能不会得到改善,但您对跨日志和其他用户的压力会小得多。

    【讨论】:

      【解决方案3】:
      1. 通过使用允许您的查询执行此操作的选项或提示来并行化您的更新;

      2. 如果不可用,您可以手动将工作拆分到单独的同时运行的更新会话中。这将要求您能够有效地拆分工作,最好使用分区。

      3. 关闭所有开销:禁用/删除索引,关闭事务日志记录以允许时间点恢复等。在您的情况下,索引不会造成损害,因为您没有更新索引列或添加新行。

        理论上具有 16 核系统(用于 CPU 架构上的超线程的 x2)。如果您没有其他瓶颈(磁盘 io),则 50 分钟的作业将在 3 分钟内运行。

      【讨论】:

        猜你喜欢
        • 2012-08-09
        • 2012-02-11
        • 1970-01-01
        • 1970-01-01
        • 2017-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多