需要优化且高效的查询

时间:2012-07-14 08:54:06

标签: sql query-optimization

PID UID Req Res

1   101 C   to
2   101 A   from
3   101 B   to
4   102 A   from
5   102 B   from

我想写一个查询来从表中获取满足以下条件的所有记录。

我想得到Res ='to'的所有记录的UID。对于这些特定的UID,我想获得Req ='A'的记录。我写了一个示例查询,它也有效。请在下面找到查询。

SELECT Res,
       UID,
       Req
FROM   TABLE
WHERE  Req = 'A'
       AND UID = (SELECT DISTINCT( UID )
                  FROM   TABLE
                  WHERE  Res = 'to') 

上述查询的问题是,在SQL Server 2008中运行时,它运行的时间超过一小时,只能获取15-20条记录。记录总数很大,因为这是一个生产表。我想知道为什么查询长时间运行以及我是否可以获得相同的优化查询。

谢谢, Prabhath

4 个答案:

答案 0 :(得分:0)

尝试使用JOIN而不是子查询:

SELECT a.Res,
       a.UID,
       a.Req
  FROM TABLE a
  JOIN (SELECT UID FROM TABLE WHERE Res = 'to' GROUP BY UID) b
       ON a.UID = b.UID
 WHERE a.Req = 'A'

答案 1 :(得分:0)

我看过其他帖子表明以下内容可能效率更高:

SELECT Res, UID, Req
FROM TABLE t
WHERE  Req = 'A' and
       exists (select * from table t2 where t2.res = 'to' and t.uid = t2.uid)

逻辑上,它做了同样的事情,但在这种情况下,相关子查询可能会产生更好的查询计划。

它还取决于选择性Req和Res是谁(涉及多行或只有几行)。如果表中的许多行满足条件,则可以使用windows函数替代公式。

答案 2 :(得分:0)

您的查询速度太慢的原因是您的引擎可能正在运行它认为的每一行的子查询,并且该查询可能是隐式聚合(因为它使用DISTINCT)。这对于每一行都要做很多工作,并且随着它进入结果集,它可能会进行大量的交换以实现它。

如果连接的行具有相同的UID 具有Res ='to',则此查询将表连接到自身。基于两个因素过滤行:具有至少一个具有相同UID和Res ='to'的匹配行,并且具有Req ='A'。

这将是一个非常快速的解决方案,原因如下:查询引擎已经过优化,可以尽快从结果集中删除行。对于行PID = 1,3和5,引擎将立即丢弃它们(甚至不执行连接),因为Req!='A'。对于行PID = 2,连接将匹配第1行,然后通常甚至不继续连接3(因为它通过DISTINCT关键字知道(并且事实上没有选择连接中的列) )匹配连接中的其他行不会更改结果集)。对于PID = 4,它将不匹配任何。

SELECT DISTINCT main_row.Res,
       main_row.UID,
       main_row.Req
FROM   TABLE AS main_row
JOIN   TABLE AS res_join 
       ON main_row.UID = res_join.UID 
       AND res_join.Res = 'to'
WHERE  main_row.Req = 'A'

答案 3 :(得分:0)

由于可能只是您使用DISTINCT引起问题,因此值得探讨。显然它们与你的原始形式非常接近。

SELECT Res, UID, Req FROM TABLE
WHERE  Req = 'A'
    AND UID = (SELECT t2.UID FROM TABLE as t2 WHERE Res = 'to' GROUP BY t2.UID)

SELECT Res, UID, Req FROM TABLE
WHERE  Req = 'A'
    AND UID = (SELECT MIN(t2.UID) FROM TABLE as t2 WHERE Res = 'to')