【问题标题】:Query Optimization : using (Union instead of OR) and (exists instead of null)查询优化:使用 (Union 而不是 OR) 和 (exists 而不是 null)
【发布时间】:2019-09-18 23:08:35
【问题描述】:

我有一个查询优化问题。

对于上下文,这个查询一直是即时运行的

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

所以我试图修复它。

查询是 Like -->

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 来优化它,并且 exists 而不是 in 但仍然需要 3 分钟

我想在 5 秒内再次完成。

您是否看到一些查询问题?

谢谢

【问题讨论】:

  • 您的 sn-p 中有 3 个查询,而不是一个。就目前而言,您的问题很模糊。
  • OR -- UNION 是什么意思? OR? A.date = Today 的子句在哪里 ` 也不是有效的语法。 TODAY 不是 t-SQL 关键字(除非 TodayABC 中的列,在这种情况下它应该使用别名)。
  • 发布解释计划。将帮助我们更好地分析
  • 除了 Larnu 提出的观点之外,您所有的连接查询在语法上都是不正确的,因为您缺少连接的 ON 位。
  • 另外,如果之前查询很快,有什么变化?

标签: sql sql-server performance tsql


【解决方案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 

【讨论】:

  • 感谢您的回答,但正如我已经说过的:我使用联合而不是 OR 和存在而不是 in 对其进行了优化,但仍需要 3 分钟。我试试左连接!
  • 抱歉!在查询的第 2 部分中,两个表都引用了同一列 colseekedinA 。那为什么要创建两个查询呢?
【解决方案2】:

exists 方法可能会产生虚假结果,因为仅当有 1 行匹配时,您才会得到不匹配任一条件的行。这可以通过在相关子查询中使用 exists 来避免,但这不是我已经尝试过的足以推荐的东西。

为了速度,我会选择交叉应用并在交叉应用表达式中指定父表(相关子查询以创建派生表)。这样,在返回数据之前就指定了连接条件,如果有问题的列上有索引(即它们是主键),那么优化器可以为此制定一个有效的计划。

在交叉应用表达式中使用全部联合,因为这可以防止派生表中的不同排序,这在成本方面通常比将数据本身返回更重(联合必须识别所有行,包括重复)。

最后,如果这仍然很慢,那么您可能希望为表 a 中的日期列添加索引。这克服了日期列固有的可搜索性不足,意味着优化器可以利用索引,而不是扫描结果集中的所有行并测试日期是否等于今天。

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 

【讨论】:

  • 唯一的问题是,如果 X 和 Z 返回相同的值,您的查询可能会返回重复项。
  • 您可以在外部查询中使用 distinct 子句,这将对最小行数进行排序,因为在调用 distinct 时已经进行了过滤。
【解决方案3】:

你的代码很混乱,但第一部分

您可以尝试使用 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 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    相关资源
    最近更新 更多