【问题标题】:SQL Server update query extremely slowSQL Server 更新查询极慢
【发布时间】:2020-11-21 16:48:44
【问题描述】:

我想对具有 c.200m 记录的表执行简单的更新语句。但是,这似乎需要很长时间。

UPDATE a
SET hybrid_trade_flag = CASE WHEN b.trade_id IS NOT NULL THEN 'Y' ELSE 'N' END
FROM [tbl_master_trades] a
LEFT JOIN [tbl_hybrid_trades_subset] b
    ON a.trade_id = b.trade_id

第一个表 tbl_master_trades 有 c.200m 条记录,并在 trade_id 和另一列(一起)上创建了一个索引。第二张桌子tbl_hybrid_trades_subset 大约有 200k。在我不得不取消它之前,这个查询运行了 40 多分钟(取消本身大约需要 30 分钟)。

我认为也许将第二个表转换为临时表并拆分语句会有所帮助,因此将其转换为以下内容:

UPDATE a
SET hybrid_trade_flag = 'Y'
FROM [tbl_master_trades] a
INNER JOIN #tmp_hybrid_trades b
    ON a.trade_id = b.trade_id

UPDATE a
SET hybrid_trade_flag = 'N'
FROM [tbl_master_trades] a
WHERE hybrid_trade_flag IS NULL

即使是上述两个查询也需要 30 分钟才能运行。我需要在第一张桌子上运行几个这样的更新(c.80),所以我不确定这是否可行,因为这需要几天时间!有人可以建议我是否/如何加快速度吗?

【问题讨论】:

  • hybrid_trade_flag 真的需要为每一行更新还是只需要根据您发布的逻辑进行刷新?将更新分解为单独的语句并在 where 子句中包含适当的过滤器以避免无意义的更新可能会更有效。
  • 混合表中存在交易的位置需要设置为“Y”,其他所有位置需要设置为“N”
  • @Chipmunk_da 。 . .更新 2 亿行将永远持续下去。也许您可以将默认值设置为“N”,然后将子查询更改为“Y”。
  • @GordonLinoff 这是个好主意!我会去做。谢谢!

标签: sql sql-server sql-update subquery query-optimization


【解决方案1】:

你遇到了 2 个问题

  • 您正在检查另一个表中是否存在 c.200m 值
  • 您正在更新基表中的 c.200m 值

要解决这个问题,您可以

  • 将适当的索引添加到查找表中
  • 避免在非严格需要的地方更新

有问题的索引是

CREATE INDEX idx_trade_id ON tbl_hybrid_trades_subset (trade_id)

要限制更新量,请使用:

UPDATE a
   SET hybrid_trade_flag = CASE WHEN b.trade_id IS NOT NULL THEN 'Y' ELSE 'N' END
  FROM [tbl_master_trades] a
  LEFT OUTER JOIN [tbl_hybrid_trades_subset] b
               ON b.trade_id = a.trade_id
 WHERE hybrid_trade_flag != CASE WHEN b.trade_id IS NOT NULL THEN 'Y' ELSE 'N' END

第一次可能还需要一段时间,但后续更新应该会快一些。

【讨论】:

    【解决方案2】:

    我将首先重写查询以使用exists

    update t
    set hybrid_trade_flag = case 
        when exists(select 1 from tbl_hybrid_trades_subset ts where ts.trade_id = t.trade_id)
        then 'Y'
        else 'N'
    end
    from tbl_master_trades t
    

    那么,我建议在tbl_hybrid_trades_subset(trade_id) 上建立一个索引,以便子查询可以快速执行。

    tbl_master_trades(trade_id) 上的索引也可能有帮助(索引中没有任何其他列),但子查询所针对的表上的索引似乎更重要。

    也就是说,200M 行仍然是需要处理的大量行,因此无论如何查询可能会花费相当多的时间。

    【讨论】:

    • 感谢@GMB!我会试试你的建议,希望它能减少执行时间
    • qq - 我将在主表上执行一些更新,而不加入任何其他表。如果在我将在 where 子句中为那些 update 语句使用的每一列上创建一个索引会有帮助吗?
    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 2019-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多