问题如下:
一张T_PO表:总数大概300W左右
select  t.poid,t.bacode,t.baupcode,t.userid,t.dsname,
        t.dsno,t.dsip,t.reid,t.subid,t.carryu,t.factory 
from T_PO t 
where t.subId='127';执行计划显示:全表扫描,cost:4945。
但是用改为:
select count(*) from T_PO t where t.subId='127';
的时候,
执行计划显示:INDEX RANGE SCAN ,COST:31 。
T_PO表中的字段subId是有对应的列的索引的。希望大家帮我看看,有没有什么办法能让我查询T_PO表能快速一些。
现在按照subId为127查询出来3W条就需要50多秒。太慢了

解决方案 »

  1.   

    也许oralce认为走全表扫描快点啥
     你可以试试 select /*+ index(t index_name)*/
    t.poid,t.bacode,t.baupcode,t.userid,t.dsname,
      t.dsno,t.dsip,t.reid,t.subid,t.carryu,t.factory  
    from T_PO t  
    where t.subId='127';
      

  2.   

    select /*+ INDEX(t.subId) */ t.poid,t.bacode,t.baupcode,t.userid,t.dsname,
      t.dsno,t.dsip,t.reid,t.subid,t.carryu,t.factory  
    from T_PO t  
    where t.subId='127';试试速度如何
      

  3.   

    收集一下统计数据
    sql>exec dbms_stats.gather_table_stats(user,'T_PO',cascade=>true);
    如果执行计划仍然是这样,表明ORACLE的执行计划是正确的。
    select count(*) from (....)不同于select t.poid...... from.
    前一语句,因为只统计记录数,且subid上的索引肯定不为空,通过访问索引就可以得出记录总数
    ,且访问索引所读块肯定少于读取表数据块数,因而使用索引范围扫描。
    后一语句,单从如果访问索引的数据加上访问表中符合条件的数据块如果大于全表扫描时所读数据块时。
    这时更倾向于使用全表扫描。
      

  4.   

    select /*+ INDEX(t.subId) */ t.poid,t.bacode,t.baupcode,t.userid,t.dsname,
      t.dsno,t.dsip,t.reid,t.subid,t.carryu,t.factory  
    from T_PO t  
    where t.subId='127';这个我也试过,一样的全表扫描。看来Oracel的执行计划是正确的,但是怎么才能让我取出T_PO表能快点呢?
      

  5.   

    做下分析,analyze table 
    然后再执行,/*+ INDEX(t.subId) */,你索引名字写错了没? 
    因为我看你的索引名字和列名相同,我们开发的时候,索引的名字和列的名字都不一样的。
      

  6.   


    我是在后台取出,然后根据t.poid去其他的4、5张表中分别查询出一些信息,然后根据一定的规则和业务逻辑计算。并不是在web展现,但是现在的问题是整个计算跑完一次大概需要3天多,而且不知道为什么在跑了200W左右的时候,程序就不跑了,而且还不报错。
      

  7.   


    刚刚去现网查看了下:
    因为我从T_PO表查询出t.poid后,需要根据t.poid去查其他的4张表,其中有3张都是一对一的,并且我在现网测了下时间,几乎不耗时,但是有一张表T_PR,T_PR表是一张千万级的表,在每个月中,一个t.poid都是对应多条T_PR表中的记录的。
    查询语句为:select * from T_PR a where a.poId=? and a.createTime>=to_date('2011-05-01 00:00:00','yyyy-MM-dd hh24:mi:ss') and a.createTime<to_date('2011-06-01 00:00:00','yyyy-MM-dd hh24:mi:ss') 
    (这里的SQL是我自己将HQL转为SQL的,原HQL为:from PR a where a.createTime>? and a.createTime<? and a.poId=?)这条语句:我在现网试了下,大概出来结果需要分钟级别。
    并且我发现现网的T_PR表居然有重名的索引,并且同一个字段还有两个索引T_PR表中索引名和字段名如下:
    索引名                    字段名
    RATE_CREATETIME_PORT      CREATETIME
    RATE_CREATETIME_PORT      POID
    RATE_COMPARESTATUS        COMPARESTATUS
    RATE_CREATETIME           CREATETIME
    RATE_CROPSTATUS           CROPSTATUS
    RATE_POID                 POID
    RATE_CONFPROFILEDOWNCODE  CONFPROFILEDOWNCODE
    RATE_SUBID                SUBID
    PK_PR                     PRID不知道这种索引是谁建出来的
      

  8.   

    2个同名的索引,应该是2个不同的oracle用户创建的吧
      

  9.   

    我执行了下
    select * from t_PortRate a 
    where a.portId=6323106 
          and a.createTime>=to_date('2011-05-01 00:00:00','yyyy-MM-dd hh24:mi:ss') 
          and a.createTime<to_date('2011-06-01 00:00:00','yyyy-MM-dd hh24:mi:ss') 用时和执行计划为:
    Elapsed: 00:02:13.17Execution Plan
    ----------------------------------------------------------
       0      SELECT STATEMENT Optimizer=CHOOSE (Cost=5 Card=1 Bytes=109)
       1    0   TABLE ACCESS (BY INDEX ROWID) OF 'T_PORTRATE' (Cost=5 Card
              =1 Bytes=109)   2    1     INDEX (RANGE SCAN) OF 'RATE_CREATETIME_PORT' (NON-UNIQUE
              ) (Cost=4 Card=45)Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
         103669  consistent gets
          79358  physical reads
          43532  redo size
           1858  bytes sent via SQL*Net to client
            503  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              1  rows processed
    请问下如何优化查询时间?
    求高手
      

  10.   

    select t.poid,t.bacode,t.baupcode,t.userid,t.dsname,
      t.dsno,t.dsip,t.reid,t.subid,t.carryu,t.factory  
    from T_PO t  
    where t.subId='127';
    subid重复情况十分太多。如果是的话,考虑创建不同的索引类型。
      

  11.   


    T_PO表总共300W,其中不同的subID总共200多个,按照subID分组取count,最多的大概6W多,最少的3K。
    创建不同的索引类型是什么意思?
      

  12.   

    返回的数据量太大,他要那么多io,用什么索引都一样。
    看你的需求比较不像普通的OLTP业务,倒像是做数据分析的。若是这样的话,考虑在设计上区分出OLTP数据库和OLAP数据库,并做针对性处理。
    不然的话,就不应该一次性读取那么多的数据。我感觉应该从另一个面来考虑这个问题。想象若有几十个客户端都像这样查询资料,那太折腾了。
      

  13.   

    select /*+ index(t,subId字段的索引名) */
     t.poid,
     t.bacode,
     t.baupcode,
     t.userid,
     t.dsname,
     t.dsno,
     t.dsip,
     t.reid,
     t.subid,
     t.carryu,
     t.factory
      from T_PO t
     where t.subId = '127';
      

  14.   

    subid的字段类型是字符型吗?
      

  15.   

    subid不是字符型,就会有类型转换,就不走索引了。
      

  16.   

    试试:
    select t.poid,
           t.bacode,
           t.baupcode,
           t.userid,
           t.dsname,
           t.dsno,
           t.dsip,
           t.reid,
           t.subid,
           t.carryu,
           t.factory
      from t_po t
     where t.subid = 127;
      

  17.   

    这个我早试过,不是这个原因。
    其实关于subid走不走索引的问题,3楼已经给出正解,因为我的问题已经转变了,在9楼我已经提出,主要是查询那张千万级的表的时候相当慢,至于后面那个联合索引是没有问题的。如果后面还有大虾帮忙看看的话,可以看看我在9楼处前面提出的问题。