具有大量 JOIN 条件的 SQL 查询非常慢

标签 sql sql-server-2008

我继承了一个 SQL Server 2008 R2 项目,其中包括从另一个表更新表:

  • Table1(大约 150,000 行)有 3 个电话号码字段(Tel1Tel2Tel3)
  • Table2(大约 20,000 行)有 3 个电话号码字段(Phone1Phone2Phone3)

.. 当这些数字中的任何一个匹配时,Table1 应该被更新。

当前代码如下:

UPDATE t1
SET surname = t2.surname, Address1=t2.Address1, DOB=t2.DOB, Tel1=t2.Phone1, Tel2=t2.Phone2, Tel3=t2.Phone3,
FROM Table1 t1 
inner join Table2 t2
on
(t1.Tel1 = t2.Phone1 and t1.Tel1 is not null) or
(t1.Tel1 = t2.Phone2 and t1.Tel1 is not null) or
(t1.Tel1 = t2.Phone3 and t1.Tel1 is not null) or
(t1.Tel2 = t2.Phone1 and t1.Tel2 is not null) or
(t1.Tel2 = t2.Phone2 and t1.Tel2 is not null) or
(t1.Tel2 = t2.Phone3 and t1.Tel2 is not null) or
(t1.Tel3 = t2.Phone1 and t1.Tel3 is not null) or
(t1.Tel3 = t2.Phone2 and t1.Tel3 is not null) or
(t1.Tel3 = t2.Phone3 and t1.Tel3 is not null);

但是,此查询需要 30 多分钟才能运行。

执行计划表明主要瓶颈是 Table1 上聚集索引扫描周围的嵌套循环。两个表的 ID 列都有聚簇索引。

由于我的 DBA 技能非常有限,任何人都可以建议提高此查询性能的最佳方法吗?将 Tel1Tel2Tel3 的索引添加到每一列是否是最佳举措,或者是否可以更改查询以提高性能?

最佳答案

乍一看,我建议从选择中删除所有 OR 条件。

看看这是否更快(它将您的更新转换为 3 个不同的更新):

UPDATE t1
SET surname = t2.surname, Address1=t2.Address1, DOB=t2.DOB, Tel1=t2.Phone1, Tel2=t2.Phone2, Tel3=t2.Phone3,
FROM Table1 t1 
inner join Table2 t2
on
(t1.Tel1 is not null AND t1.Tel1 IN (t2.Phone1, t2.Phone2, t2.Phone3);

UPDATE t1
SET surname = t2.surname, Address1=t2.Address1, DOB=t2.DOB, Tel1=t2.Phone1, Tel2=t2.Phone2, Tel3=t2.Phone3,
FROM Table1 t1 
inner join Table2 t2
on
(t1.Tel2 is not null AND t1.Tel2 IN (t2.Phone1, t2.Phone2, t2.Phone3);

UPDATE t1
SET surname = t2.surname, Address1=t2.Address1, DOB=t2.DOB, Tel1=t2.Phone1, Tel2=t2.Phone2, Tel3=t2.Phone3,
FROM Table1 t1 
inner join Table2 t2
on
(t1.Tel3 is not null AND t1.Tel3 IN (t2.Phone1, t2.Phone2, t2.Phone3);

关于具有大量 JOIN 条件的 SQL 查询非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16834476/

相关文章:

sql - 将所有同义词更改为另一个数据库

sql-server - 何时需要在 try catch block 中检查 @@trancount > 0 ?

tsql - SQL MERGE语句中的UPDATE-no-op

mysql - SQL从表到表的插入被源表中的重复主键阻止

sql - 更改包含数据的表中列的大小

php - 有什么方法可以通过在 SQL 中执行 DELETE 指令来返回一些东西吗?

sql - 我该如何解决 "Either the parameter @objname is ambiguous or the claimed @objtype (COLUMN) is wrong."?

.net - 经典 ADO.NET - 如何将 UDT 传递给存储过程?

sql - 如何将引用类型: External Reference的父变量值传递给子包

c# - SQL Server - 传递带有计算列的表值参数