【问题标题】:Many-column UPDATE-JOIN with many-ISNULL takes a long time?带有 many-ISNULL 的多列 UPDATE-JOIN 需要很长时间?
【发布时间】:2012-05-02 21:49:56
【问题描述】:

我们的数据库中有一个存储过程,它通过使用 where 条件连接 30 列上的 2 个表来更新表。 SQL 的一般格式为:

UPDATE Target
SET col1 = Source.col1
INNER JOIN Source 
on 
ISNULL(Target.Col2, '') = ISNULL(Source.Col2, '') and
ISNULL(Target.Col3, '') = ISNULL(Source.Col3, '') and
.
.
.
ISNULL(Target.Col31, '') = ISNULL(Source.Col31, '') and 

这是查询计划。将其保存到您的 PC 并重新打开,以便更好地扩展。

Source 表有 65M 记录,Target 有 165M。以前它曾经在几分钟内运行。考虑到查询的丑陋和潜在的低效,我觉得这很令人惊讶。这个月它运行了 1.5 小时,使用了 100% 的处理器,我们不得不杀死它。

对如何即兴发挥以下查询并使其按时运行有什么建议吗?

我们在 30-col 连接条件中使用的一些列上有单列索引。

我知道 ISNULL 函数和 30 列上的连接是疯狂的,这是一个糟糕的设计。别怪我,我继承了这个经济。

很遗憾,没有时间重新设计。有什么建议吗?

【问题讨论】:

  • 自上个月以来发生了什么变化?
  • 将所有 NULL 更新为 '',然后在没有 ISNULL 的情况下运行查询。但是 Remus 的问题非常中肯,那段时间发生了哪些变化
  • 您是否考虑过将其重写为合并?您是否考虑过使这些列不可为空以消除 60 个 ISNULL 调用?
  • 您可以检查查询计划并尝试修改查询以确保使用最有效的索引
  • @erikxiv - 由于 ISNULL,我不认为索引将被用于最大效果。

标签: sql sql-server-2008 join isnull


【解决方案1】:
  1. 请发一张预计执行计划的截图
  2. 我怀疑以前的查询使用了哈希连接(它应该这样做),但不知何故,基数估计现在出错了,你得到了一个循环连接。在查询上添加一个哈希连接提示,看看它是否解决了这个问题 (INNER HASH JOIN)。一旦我们有了确切的计划,我们就可以说更多。
  3. 将等式更改为(A1 = A2 OR (A1 IS NULL AND A2 IS NULL))。 SQL Server 实际上识别出这种模式并在内部将其转换为“完全等于没有愚蠢的空语义”。即使是空值,您也可以通过这种方式查找索引。

如果这没有帮助,请务必执行步骤 (3) 并在 col2-col31 上创建一个覆盖索引,包括 col1。这将为您提供一个合并连接,这是在这种情况下可能最有效的计划。它真的很快。警告:这将使表的磁盘大小加倍并减慢更新速度。

【讨论】:

  • 我添加了计划。见我修改后的帖子。关于您关于删除 ISNULL 函数的评论,如果 A1 或 A2 为空但不是两者都为空怎么办?
  • 是的,哈希连接提示可以解决这个问题。
  • @usr 如何在查询中加一?
  • 说“INNER HASH JOIN”而不是“INNER JOIN”。
【解决方案2】:

DBa 建议我们按照查询分析器的建议添加一个包含所有 30 列的索引,其中大多数是“包含”列。这允许查询完成。下个月我们运行时,通常在 1.5 小时内运行的相同更新 SQL 并没有在 24 小时内完成。当我们运行更新统计信息时,它在一小时内完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-26
    • 2014-09-26
    • 1970-01-01
    • 2016-12-03
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多