将IN和UNION转换为更高效的东西(可能是EXISTS)

时间:2013-01-25 17:59:02

标签: sql sql-server tsql

SELECT * 
FROM   sec 
WHERE  sec.cu IN (SELECT s.cu 
                  FROM   sec s WITH (nolock) 
                  WHERE  EXISTS (SELECT * 
                                 FROM   hact h WITH ( nolock), 
                                 JOIN   dport p WITH ( nolock) ON h.ic = p.ic
                                 WHERE  s.cu = h.cu )

                  UNION 
                  SELECT s.cu 
                  FROM   sec s WITH (nolock) 
                  WHERE  EXISTS(SELECT * 
                                FROM   schanges c WITH ( nolock) 
                                WHERE  s.cu = c.cu) 
                  UNION 
                  SELECT s.cu 
                  FROM   sec s WITH (nolock) 
                  WHERE  s.cu IN (SELECT DISTINCT cu 
                                  FROM   suk WITH (nolock))) 
       AND EXISTS (SELECT * 
                   FROM   hact h WITH (nolock) 
                          JOIN port p WITH (nolock) 
                            ON h.ic = p.ic 
                   WHERE  sec.cu = h.cu 
                          AND p.ptype = 'X') 

嗨,我有这个问题,我正在尝试优化。我试图将其转换为删除联合和转换为更可读但失败。我试图提高效率,可能只使用EXISTS而不是EXISTS。

5 个答案:

答案 0 :(得分:2)

这是一个应该在功能上等同的简化版本:

SELECT s.*
FROM   sec s WITH (nolock) 
WHERE (
  EXISTS (
    SELECT * 
    FROM   hact h WITH ( nolock)
    JOIN   dport p WITH ( nolock) 
      ON h.ic = p.ic
    WHERE  s.cu = h.cu 
  ) OR EXISTS (
    SELECT * 
    FROM   schanges c WITH ( nolock)
    WHERE  s.cu = c.cu
  ) OR EXISTS (
    SELECT *
    FROM   suk WITH (nolock)
    WHERE  s.cu = suk.cu
  )
) AND EXISTS (
  SELECT * 
  FROM   hact h WITH (nolock) 
  JOIN port p WITH (nolock) 
    ON h.ic = p.ic 
  WHERE  
    s.cu = h.cu 
    AND p.ptype = 'X'
)

答案 1 :(得分:2)

我认为你可以用这种方式重写你的嵌套in / exists:

SELECT * 
FROM sec 
WHERE sec.cu IN (
  SELECT s.cu 
  FROM sec s 
  INNER JOIN hact h ON s.cu = h.cu, 
  INNER JOIN dport p ON h.ic = p.ic

  UNION ALL

  SELECT s.cu
  FROM sec s
  INNER JOIN schanges c ON s.cu = c.cu) 

  UNION ALL

  SELECT s.cu 
  FROM sec s 
  INNER JOIN suk k ON k.cu = s.cu
  INNER JOIN hact h ON s.cu = h.cu
  INNER JOIN port p ON h.ic = p.ic AND p.ptype = 'X'
)

甚至完全从子查询中删除sec表:

SELECT * 
FROM sec 
WHERE sec.cu IN (
  SELECT h.cu 
  FROM hact h
  INNER JOIN dport p ON h.ic = p.ic

  UNION ALL

  SELECT cu
  FROM schanges

  UNION ALL

  SELECT k.cu 
  FROM suk k
  INNER JOIN hact h ON s.cu = h.cu
  INNER JOIN port p ON h.ic = p.ic AND p.ptype = 'X'
)

答案 2 :(得分:1)

只需将您的UNION子句更改为UNION ALL即可。仅此一点应该有所帮助。

为了能够在没有我们盲目猜测的情况下为您提供帮助,您将不得不向我们提供表格,密钥和索引定义以及查询计划。

答案 3 :(得分:0)

未经测试,但我认为您可以使用连接

来执行此操作
select distinct s.*
from   sec s with (nolock)
join   hatch h1 with (nolock)
  on   h1.cu = s.cu
       join  port p1 WITH (nolock) 
         ON  h1.ic = p1.ic
        AND  p1.ptype = 'X'
left join hact h2 WITH ( nolock)
  on   h2.cu = s.cu
       join  port p2 WITH (nolock) 
         ON  h2.ic = p2.ic
left join  schanges c WITH ( nolock) 
  on   s.cu = c.cu 
left join  suc WITH ( nolock) 
  on   s.cu = suc.cu 
where h2.cu  is not null
   or c.cu   is not null
   or suc.cu is not null

union intersect可能会更快 取决于查询优化器的智能程度

(   
    select s.*
    from   sec s with (nolock)
    join hact h2 WITH (nolock)
      on   h2.cu = s.cu
           join  port p2 WITH (nolock) 
             ON  h2.ic = p2.ic
  union
    select s.*
    from   sec s with (nolock)
    join  schanges c WITH ( nolock) 
      on   s.cu = c.cu 
  union
    select s.*
    from   sec s with (nolock)
    left join  suc WITH ( nolock) 
      on   s.cu = suc.cu
)
  intersect
    select s.*
    from   sec s with (nolock)
    join   hatch h1 with (nolock)
      on   h1.cu = s.cu
           join  port p1 WITH (nolock) 
             ON  h1.ic = p1.ic
            AND  p1.ptype = 'X'

我已经看到优化器在这些二级连接上变得愚蠢 如果是这样,试试

select s.*
from   sec s with (nolock)
join hact h1 WITH (nolock)
  on h1.cu = s.cu
  where h1.ic in (select ic from where ptype = 'X')

请参阅我对死锁的评论和(nolock) 我不考虑(nolock)一个kludge并使用它很多。
如果你看到很多死锁,那么你需要看一下。

索引cu,ic和ptype。
然后测试不同版本的查询并查看执行计划 这是查询优化器可能遇到问题的查询类型 查询优化器基于统计信息,甚至可以更改执行计划 您可能需要包含联接的表提示。

答案 4 :(得分:0)

我在想:(未经测试,希望保持功能等同性)

SELECT DISTINCT s.*
FROM   sec s
JOIN hact h WITH (nolock)
  ON s.cu = h.cu
LEFT JOIN dport p WITH (nolock)
  ON h.ic = p.ic
LEFT JOIN schanges c WITH (nolock)
  ON s.cu = c.cu
LEFT JOIN suk WITH (nolock)
  ON suk.cu = s.cu
JOIN port p2 WITH (nolock)
  ON h.ic = p2.ic 
WHERE p2.ptype = 'X' AND
  (p.ic IS NOT NULL OR c.cu IS NOT NULL OR suk.cu IS NOT NULL)

修改:添加了DISTINCT