【问题标题】:Subquery in a join is slowing down performance, looking for a better alternative连接中的子查询正在降低性能,正在寻找更好的替代方案
【发布时间】:2017-02-14 17:52:17
【问题描述】:

下面是一个类似于我正在使用的代码的 sn-p。

DECLARE
    @UserParam = NULL    --optional paramater

SELECT 
    rtrim(item)         [aKey]
INTO
    #aKeyTable
FROM 
    myDB.dbo.fnSplit(@UserParam,',') 

SELECT
/* Lots of columns, not important to the question */
FROM
   myDB.dbo.tableB b
   JOIN myDB.dbo.tableC c ON c.cKey = b.bKEY
       AND (c.columnA IN
           (
           SELECT
               aKey
           FROM
               #aKeyTable
           )
               OR @UserParam IS NULL)

我的问题是:如何删除子查询以提高性能。

要求:

  • @UserParam 是可选的
  • @UserParam 可以有多个逗号分隔的参数
  • @UserParam 必须匹配 tableC 中的 columnA 或者为 NULL
  • 使用 WHERE 子句也不是一种选择,它也会对性能影响太大

我使用的是 SQL Server 2014

更新:我的整个查询很长,平均需要大约 15-20 秒才能运行,具体取决于参数,但根据执行计划,这个子查询使用了 89% 的性能。我在之前的 WHERE 子句中有它,性能相当,有时更慢。

谢谢

【问题讨论】:

  • AND (c.columnA IN 应该是WHERE . . .

标签: sql-server performance join subquery


【解决方案1】:

没有查询计划就很难确定;也就是说,也许在 aKey 列上创建一个索引?

【讨论】:

  • 我将此标记为答案 - 我没有创建索引的权限,但执行计划指出缺少索引。我将查询更改为使用已编入索引的表/列。我还重新排序了一些 JOINS,最后我根据参数从 15-20 秒缩短到不到一秒。
【解决方案2】:

您是否考虑过使用TVP?他们最适合这个目的。另请阅读Erland Sommarskog 了解更多详情。

将不同的案例组合成一个执行计划是有问题的。当@UserParam 为空时,情况与不为空时完全不同。你应该有每个案例的执行计划。您可以诱导 IF 并进行两次查询。对于更多参数,您最终会得到动态 sql,因为组合的指数增长是无法管理的。

优化器应将表变量的行数估计为 1,从而导致索引查找。如果参数的选择性很好,这应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-10
    • 1970-01-01
    • 2021-08-26
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多