联接中的子查询会降低性能,寻找更好的替代方案

时间:2017-02-14 17:52:17

标签: sql-server performance join subquery

下面是一段类似于我正在使用的代码片段。

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子句中有它,性能可比,有时慢。

由于

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

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

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

表变量的行数应由优化器估计为1,从而导致索引搜索。如果参数的选择性良好,这应该有效。