select * from table1 where id1 in 
(
  select id1 from table2 where ...
)在table1表的id1字段上已经建了索引(为方便描述取名"idx1"),
括号里面的查询结果不多只有几百条,table1有几百万记录。
我看了sql的执行计划,如果不加hint的话就会对table1做全表扫描。
我想如果能使用上索引idx1,肯定会快得多。 
但是怎么才可以用上索引idx1呢?我试过这样修改
select /*+ index (table1 idx1)*/ * from table1 where id1 in 
(
  select id1 from table2 where ...
)
这个更糟糕,是用idx1访问了整个表..
熟悉SQL调优的高手,可以给我一些建议吗?

解决方案 »

  1.   

    大家不妨试试select * from table1 where id1 in 
    (
      select 1000 from dual
    )很明显这个SQL用索引idx1能够在瞬间内完成查询,但是事实上Oracle会对table1做全表扫描,不会用索引,不信大家试试select * from table1 where id1 in (1000,1001)
    这个sql就才会用上idx1
      

  2.   

    有了一点进展用 /*+ FIRST_ROWS */ 是可以使用索引idx1的。但是这个方法不稳定,可控性不强,如果把查询语句稍作修改,加个去掉重复的distinct则又回到全表扫描了select distinct id3 from table1 where id1 in 
    (
      select id1 from table2 where ...
    )
      

  3.   

    表分析过了没有呢,数据库是什么优化模式的?
    若是cbo优化模式,要使用上索引必须要对表进行分析。Select last_analyzed,table_name from dba_tables where table_name='PSCP_SMS_SENT';查看表最后一次的分析时间;exec dbms_stats.gather_table_stats (ownname=>'cch',tabname=>'cch_interactions_motive',degree=>2,cascade=>TRUE);对表进行分析,这个过程依据你的表的数据量。
      

  4.   

    语句建议改为:
    select * from table1 where exists  
    (
      select 1 from table2 where id1=table1.id1
    )
      

  5.   

    同意楼上的,不适用没用上索引的语法问题,in子句本身就限制了索引的使用。
    在性能优化时首先考虑使用exists或者not exists替换in或者not in。
    这是第一步。