分别执行两条语句,它们之间仅仅adminaccount条件不同,一个是admin,一个是lgm。 
为什么用时差距这么大,而且条件为admin的语句符合的记录多,用时少。而条件为lgm的语句符合的记录少,用时多。 在powerscope  表中有两个索引一个是powerscope  表的ID,一个是adminaccount,
但奇怪的是为什么当adminaccoun='lgm'的时候用到adminaccount索引,
而当adminaccount='admin'的时候却没有用到adminaccount索引,
更为奇怪的是用到adminaccount索引的执行计划只是在adminaccount='lgm'的执行计划中出现,而且它的速度还慢。select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps 
where art.column_id=aps.scopestr  and    aps.funcnodepath ='A001' and    aps.adminaccount='admin'; 
执行这条语句后有1795条符合,用时0.531秒 执行计划如下: 
PLAN_TABLE_OUTPUT  
1 Plan hash value: 3857331516  
2    
3 -------------------------------------------------------------------------------------------  
4  ¦ Id   ¦ Operation           ¦ Name                  ¦ Rows   ¦ Bytes  ¦ Cost (%CPU) ¦ Time      ¦  
5 -------------------------------------------------------------------------------------------  
6  ¦   0  ¦ SELECT STATEMENT    ¦                       ¦ 44229  ¦  3196K ¦  4344   (1) ¦ 00:00:53  ¦  
7  ¦*  1  ¦  HASH JOIN          ¦                       ¦ 44229  ¦  3196K ¦  4344   (1) ¦ 00:00:53  ¦  
8  ¦*  2  ¦   TABLE ACCESS FULL ¦ POWERSCOPE            ¦   541  ¦ 16230  ¦    56   (2) ¦ 00:00:01  ¦  
9  ¦   3  ¦   TABLE ACCESS FULL ¦ CMSARTICLE            ¦ 40782  ¦  1752K ¦  4288   (1) ¦ 00:00:52  ¦  
10 -------------------------------------------------------------------------------------------  
11    
12 Predicate Information (identified by operation id):  
13 ---------------------------------------------------  
14    
15    1 - access("APS"."SCOPESTR"=TO_NUMBER("ART"."COLUMN_ID"))  
16    2 - filter("APS"."ADMINACCOUNT"='admin' AND   
17               "APS"."FUNCNODEPATH"='A001')  ----------------------------------------------------------- 
select art.article_id,art.article_title,aps.adminaccount from cmsarticle art,powerscope aps 
where art.column_id=aps.scopestr  and    aps.funcnodepath ='A001' and    aps.adminaccount='lgm'; 
执行这条语句后有148条符合,用时3.906秒 执行计划如下: 
PLAN_TABLE_OUTPUT  
1 Plan hash value: 2231333241  
2    
3 -----------------------------------------------------------------------------------------------------  
4  ¦ Id   ¦ Operation                     ¦ Name          ¦ Rows   ¦ Bytes  ¦ Cost (%CPU) ¦ Time      ¦  
5 -----------------------------------------------------------------------------------------------------  
6  ¦   0  ¦ SELECT STATEMENT              ¦               ¦   888  ¦ 65712  ¦  4291   (1) ¦ 00:00:52  ¦  
7  ¦*  1  ¦  HASH JOIN                    ¦               ¦   888  ¦ 65712  ¦  4291   (1) ¦ 00:00:52  ¦  
8  ¦*  2  ¦   TABLE ACCESS BY INDEX ROWID ¦ POWERSCOPE    ¦    11  ¦   330  ¦     3   (0) ¦ 00:00:01  ¦  
9  ¦*  3  ¦    INDEX RANGE SCAN           ¦ SYS_LGM       ¦    87  ¦        ¦     1   (0) ¦ 00:00:01  ¦  
10  ¦   4  ¦   TABLE ACCESS FULL          ¦ CMSARTICLE    ¦ 40782  ¦  1752K ¦  4288   (1) ¦ 00:00:52  ¦  
11 -----------------------------------------------------------------------------------------------------  
12    
13 Predicate Information (identified by operation id):  
14 ---------------------------------------------------  
15    
16    1 - access("APS"."SCOPESTR"=TO_NUMBER("ART"."COLUMN_ID"))  
17    2 - filter("APS"."FUNCNODEPATH"='A001')  
18    3 - access("APS"."ADMINACCOUNT"='lgm')  
------------------------------------------------------- 

解决方案 »

  1.   

    执行计划选择的选择会和数据有关系,从因为Oracle是基于成本的优化方案, 
    所以有数据的采样率会影响执行计划的选择, 
    我做一个假设: 
    假设我们有一个表,叫TableA,它有三个字段分别是ColA,ColB,ColC,表没有主键,所有字段都非空。 
    ColB值只能是('sys','user','costomer')这三种的其中一种,数据表中有一万记录。 
    数据的分布分别是(2%,95%,3%) 
    再假设,我们在ColB上有一个B树索引。 如果我们写这样的Sql: 
    SELECT * 
      FROM TableA 
     where ColB = 'user' 你说上面的SQL一定会使用在ColB上的索引吗? 
    结果是根据统计做出分析,执行计划会随着数据变化而变化。 
    以上SQL多数时候是不使用索引的,因为Select字段的*影响了执行计划, 
    假设Oralce通过索引进行快速扫描,那么它会执行9500次检索,但为了 
    取得ColA和ColC它不的不在通过 Rowid获取数据,获取数据需要9500次, 
    这样Oracle 就需要 19000次操作才能完成工作。 但是要是使用全表扫描只需要1万次就可以搞定了, 
    所以这时候Oracle会选择全表扫描。 如果我们现在改造一下: 
    SELECT ColB  
      FROM TableA 
     where ColB = 'user' 可以肯定的说,Oracle一定会使用索引。 在绝大多数Oracle可以自己维护统计信息, 
    但是特殊的时候需要人工接入,很多时候你会听到, 
    DBA抱怨,原来的SQL运行的很好,但是执行完统计后, 
    SQL变的超级慢之类的话题,SQL没有改变,但是统计信息发生了变化, 
    直接影响执行计划。 在特定的环境下,全表扫描回比索引执行的快,这是正常的。不知道这样解释对你有帮助没有,现在在上班,所以写的仓促了些, 
    多多包涵,不明白请提问。
      

  2.   

    能不能是因为符合admin和lgm帐号的用户数据的分布有关,比如虽然amdin的记录多,但是分布比较集中所以速度快。而lgm的记录虽然少,但分布比较分散所以速度快呢。
      

  3.   

    刚才大连的网全短线了,郁闷。你试验一下这个SQL,它强制使用全表扫描。
    -------------------------------------------
    select /*+ FULL(aps) */  art.article_id, art.article_title, aps.adminaccount
      from cmsarticle art, powerscope aps
     where art.column_id = aps.scopestr
       and aps.funcnodepath = 'A001'
       and aps.adminaccount = 'lgm';
      

  4.   

    从你的SQL和你原来的说明,
    你的索引也有可能问题,不过需要试验:你创建一个Index:
    create index idx_powerscope_1 on powerscope (scopestr, funcnodepath, adminaccount);来增加数据的差异性,你可以试验一下,并提供执行计划。