具有多个左外连接的 SQL Server 查询挂起

Posted

技术标签:

【中文标题】具有多个左外连接的 SQL Server 查询挂起【英文标题】:SQL Server Query having multiple left outer joins hangs 【发布时间】:2014-08-06 07:20:55 【问题描述】:

我有两张表,例如:table1 和 table2 如下 表 1(id,描述) Table2(id, col1, col2.. col10.....)

表 2 中的 col1 到 col10 可以与表 1 中的 id 字段链接。

我写了一个查询,它有 10 个 table1 实例(每个实例将 col1 链接到 table2 的 col10)

select t2.id, t1_1.desc, t1_2.desc,.....t1_10.desc from table2 t2
 left outer join table1 t1_1 on t1_1.id = t2.col1
 left outer join table1 t1_2 on t1_2.id = t2.col2
 left outer join table1 t1_3 on t1_3.id = t2.col3
.
.
.
  left outer join table1 t1_10 on t1_10.id = t2.col10
where t2.id ='111'

此查询在 Sp 内部,当我尝试在 SSMS 中执行 Sp 时,它可以正常工作。

但是,当我的 Web 应用程序运行时,查询对少数 where 子句值有效,而 hangs 对于少数。

我检查了查询的成本,并在 table2 中用这 10 列创建了一个非聚集索引。发现连接的成本降低到 0。但是,我仍然看到查询挂起

表 1 有 500 行,表 2 有 700 行。 谁能帮忙。

【问题讨论】:

更新了问题。 请包含查询执行计划,以便在 SSMS 中快速运行。在SSMS中运行时参数值可能不同吗?每个左外连接可以匹配多少条记录?如果它可以匹配多个,如果查询优化器没有正确的约束和统计信息来“理解”查询,那么它可能是一个非常昂贵的查询。 【参考方案1】:

首先,为什么要重新加入表 10 次,而不是一次加入 10 个谓词?

 left outer join table1 t1_1 on t1_1.id = t2.col1
 left outer join table1 t1_2 on t1_2.id = t2.col2
 left outer join table1 t1_3 on t1_3.id = t2.col3
.
.
.
  left outer join table1 t1_10 on t1_10.id = t2.col10

对比

 left outer join table1 t1 on t1.col1 = t2.col1 
 and t1.col2 = t2.col2
 and t1.col3 = t2.col3

只是想提出这个问题,因为像这样 10 次重新加入同一张桌子是非常不寻常的。

就您的查询计划而言,sql server 会嗅探查询中使用的第一个参数并缓存该查询计划以供将来查询使用。这个查询计划对于某些 where 子句值可能是一个好的计划,而对于其他 where 子句值是一个不好的计划,这就是为什么有时它表现良好而有时却不是。如果您的表列中有偏差(某些 where 子句值具有大量重复值),那么您可以考虑在查询中使用 OPTION(RECOMPILE) 来强制它在每次调用时制定新的执行计划。这有利有弊,请参阅此答案以进行讨论OPTION (RECOMPILE) is Always Faster; Why?

【讨论】:

以上是关于具有多个左外连接的 SQL Server 查询挂起的主要内容,如果未能解决你的问题,请参考以下文章

具有许多表、左外连接和 where 子句的 LINQ 查询

对两个 MySQL 查询执行左外连接?

具有多个或条件的sql server外连接

使用子查询改进 MySql 查询左外连接

LINQ:具有多个条件的左外连接

MySQLDQL之连接查询