查询优化:使用(联合而不是OR)和(存在而不是null)

时间:2019-04-30 09:53:52

标签: sql sql-server performance tsql

我有一个查询优化问题。

对于上下文,此查询始终一直在立即运行

但是今天花费了更多时间。 (3h +)

所以我试图修复它。

查询就像->

Select someCols from  A 
 inner join B left join C   
Where A.date = Today 
And (A.col In ( Select Z.colseekedinA from tab Z)    --A.col is the same column for 
                                          -- than below
       OR
     A.col In ( Select X.colseekedinA from tab X)   

     )


    --    PART 1 ---
  Select someCols from  A 
  inner join B left join C    -- takes 1 second 150 lines
  Where A.date = Today 

   -- Part 2 ---
  Select Z.colseekedinA from tab Z
  OR  -- Union                         -- takes 1 seconds 180 lines
 Select X.colseekedinA from tab X

当我现在将两个部分与In一起加入时,查询的时间变得非常长。

所以我使用Union或OR对其进行了优化,并且存在而不是in 但仍然需要3分钟

我想在5秒内再次完成它。

您看到一些查询问题吗?

谢谢

3 个答案:

答案 0 :(得分:1)

使用UnionExists

Select someCols 
from  A 
inner join B on a.col = b.col
left join C  on b.col = c.col
Where A.date = Today 
and exists(
 Select Z.colseekedinA from tab Z where Z.colseekedinA = A.col
 Union                        
 Select X.colseekedinA from tab X where x.colseekedinA = A.col )

此外,如果可能的话,将下面的联接更改为Left联接。

inner join B on a.col = b.col 

答案 1 :(得分:1)

existing方法可能会产生虚假的结果,因为即使有1行匹配,您也会得到不符合任一条件的行。可以通过在相关子查询中使用存在来避免这种情况,但这不是我已经尝试推荐的东西。

为了提高速度,我将进行交叉应用并在交叉应用表达式内指定父表(相关子查询以创建派生表)。这样,在返回数据之前就指定了连接条件,如果所讨论的列上都有索引(即它们是主键),那么优化器可以为此制定出有效的计划。

union all在交叉应用表达式中使用,因为这可以防止派生表中出现明显的排序,这种排序通常在成本方面比带回数据本身要重(工会必须标识所有行,包括重复项)。

最后,如果这仍然很慢,则可能要向表a中的date列添加索引。这克服了日期列固有的可保留性不足的问题,这意味着优化程序可以利用索引而不是扫描结果集中的所有行并测试日期是否等于今天。

Select someCols from  A 
 inner join B left join C   
 cross apply (Select Z.colseekedinA from tab Z where a.col=z.colseekedinA
              union all
              Select X.colseekedinA from tab X where a.col=x.colseekedina) d
Where A.date = Today 

答案 2 :(得分:0)

您的代码很混乱,但对于第一部分

您可以尝试对内部子查询使用select UNION(这些与OR一起使用) 并避免使用内部JOIN

的IN子句
    Select someCols from  A 
    inner join B 
    left join C   
    INNER JOIN (
        Select Z.colseekedinA from tab Z
        UNION                                   
        Select X.colseekedinA from tab X
    ) t  on A.col = t.colseekedinA 
    Where A.date = Today