优化子查询

时间:2014-07-26 12:31:51

标签: sql oracle

假设有三列ename , city , salary。此表中有数百万行名为emp

    ename  city    salary 
    ak    newyork  $5000
    bk    abcd     $4000
    ck    Delhi    $4000
    ....................
    ...................
   Maverick  newyork  $8000

我想检索名称与city相同Maverick的所有员工。

select * from emp where 
city = (select city from emp where ename= 'maverick' ) 

我知道它会起作用,但出于性能原因,此查询不好,因为此查询中存在两个where子句。

我需要一个比上述查询具有更好性能的查询。

4 个答案:

答案 0 :(得分:1)

这会给你相同的输出,但我怀疑它会有更好的表现。

你可以比较一下这些计划。

select x.*
  from emp x
  join (select city from emp where ename = 'maverick') y
    on x.city = y.city

您还可以添加2个索引,一个在ENAME列上,另一个在CITY列上。

create index emp_idx_ename on emp(ename);
create index emp_idx_city on emp(city);

第一个索引将加速其结果正在加入的内联视图,因为它正在搜索员工的表格。

第二个索引将加速父查询,因为它正在搜索表中的给定城市。

您可以像其他人建议的那样在emp(city,ename)上创建一个复合索引,因为您只选择了ename为X的city列,允许内联视图中的查询仅使用索引和不是表,我最初没有想到的。它可能会提供额外的提升,或多或少,取决于表的大小,虽然索引也会更大。

为了确保索引会立即使用与该表相关的更新统计信息,我还会在您创建上述索引后运行以下命令,以便您的查询立即开始使用它们:

analyze table emp compute statistics;

答案 1 :(得分:1)

Oracle可能会很好地为此查询获取最佳执行计划:

select *
from emp 
where city = (select city from emp where ename= 'maverick' ) ;

有助于查询的是两个索引:

create index idx_emp_ename_city on emp(ename, city)
create index idx_emp_ename_city on emp(city)

第一个将用于子查询。第二个查找所有匹配的行。如果没有索引,Oracle将不得不至少读取一次表(我认为至少两次),这将影响这么大的表上的性能。

答案 2 :(得分:0)

有时复杂性会因为进一步缩小查询范围而获胜。只是无法进一步优化此查询。

您可以选择添加索引以创建更好的效果。该索引应该出现在cityename

尝试使用此方法创建这些索引:

create index emp_city -- for the outer where clause
on emp
( city
)

create index emp_ename_city -- for the sub query
on emp
( ename
, city
)

答案 3 :(得分:0)

您可以使用with声明...用户建议您使用多个部门

WITH new_city_tab AS (
  SELECT city AS ncity
  FROM   emp WHERE ename='Maverick'
  GROUP BY city)
SELECT *
FROM   emp e,
       new_city_tab c
WHERE  E.city = c.ncity;