【问题标题】:Ways to help optimise a SQL update join帮助优化 SQL 更新连接的方法
【发布时间】:2014-08-24 23:04:44
【问题描述】:

我是 SQL 的新手,如果这个问题很愚蠢,我深表歉意!我有以下查询,它运行非常非常缓慢。上次我尝试它还创建了一个如此大的日志文件,以至于它用日志文件填充了驱动器,因此在完成查询之前抛出了一个错误。我只是想要一些简单的提示,请了解如何优化它或指向我可以遵循的任何有用资源。 非常感谢!

alter table Recalc_tmp1
add   [Fraction1] float,
      [Fraction2] float
go
update Recalc_tmp1
set [Fraction1] = case when b.[Numerator1] <> 0 then cast(b.[Numerator1] as float)/cast(b.[Denominator1] as float) else null end,
    [Fraction2] = case when b.[Numerator2] <> 0 then cast(b.[Numerator2] as float)/cast(b.[Denominator2] as float) else null end
from Recalc_tmp1 a
left join WriteDowns b
on a.ID1 = b.ID1 AND a.ID2 = b.ID2 AND a.ID3 = b.ID3

我更改了一些字段名称,它们在我的实际数据中更符合逻辑! WriteDowns 表相对较小,但Recalc_tmp1 表很大(数千万行),即并非Recalc_tmp1 表中的所有条目在WriteDowns 表中都有匹配项。 ID1 在两个表上都有索引

我最初将其作为 select.. into 连接查询,但在使用执行计划将其与 update 连接选项进行比较时,select into 选项的速度要慢一倍。

【问题讨论】:

  • 我认为您的意思是检查 Denominator1 和 Denominator2 是否不为零。另外,如果 ID1 是两个表中的主键,为什么还要检查 ID2 和 ID3?
  • 如果您使用来自 b 的值来填充 a 并且在其他情况下保留为空,为什么要使用左连接。将其更改为内部联接,您的查询将运行得更快并获得预期结果
  • @DavidN - 你是对的,ID1 列实际上不是主键。但它们在两个表中都有索引。

标签: sql sql-server optimization query-optimization


【解决方案1】:

类似这样的:

;with WriteDowns_cte as
(
select ID1, 
    case when [Denominator1] <> 0 then cast([Numerator1] as float)/cast([Denominator1] as float) end [Fraction1],
    case when [Denominator2] <> 0 then cast([Numerator2] as float)/cast([Denominator2] as float) end [Fraction2] 
from WriteDowns
)
update Recalc_tmp1
set [Fraction1] = b.[Fraction1],
    [Fraction2] = b.[Fraction2]
from Recalc_tmp1 a
join WriteDowns_cte b
on a.ID1 = b.ID1

【讨论】:

    【解决方案2】:

    显然是让 LEFT 加入 INNER 加入。除非您需要更新 Recalc_tmp1 中在 WriteDowns 中没有对应匹配的行?
    这也是日志文件增长如此之多的原因。几千万的每一行都得写日志记录更新。
    如果您确实需要更新所有行,那么您需要找到一种方法来运行多个更新语句,每个更新语句都会更新表的一部分。确保一次只运行一个,并确保在开始下一批之前提交所有事务。

    【讨论】:

    • 谢谢,原因的解释有帮助
    猜你喜欢
    • 2014-08-03
    • 2014-02-06
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 2023-01-27
    相关资源
    最近更新 更多