SQL優化--強制走索引失效的情況

wadekobe9發表於2012-02-27
select count(0) from creditguarantee cg where 1=1

           and cg.createddate>=to_date('2012-02-23','yyyy-MM-dd')
           and cg.createddate<=to_date('2012-02-26','yyyy-MM-dd')   
           and 2=
            (case
              when
                 (select count(0) from creditlevelchange where customerid=cg.customerid and createddate<=to_date('2012-02-26','yyyy-MM-dd'))>0
              then   
                 (select newlevel from creditlevelchange where customerid=cg.customerid and
                   changeid=
                     (select max(changeid) from creditlevelchange where customerid=cg.customerid and createddate<=to_date('2012-02-26','yyyy-MM-dd'))
                  ) 
              else
                 (case
                    when
                     (select count(0) from creditlevelchange where customerid=cg.customerid and createddate>to_date('2012-02-26','yyyy-MM-dd'))>0
                    then   
                     (select oldlevel from creditlevelchange where customerid=cg.customerid and
                       changeid=
                         (select min(changeid) from creditlevelchange where customerid=cg.customerid and createddate>to_date('2012-02-26','yyyy-MM-dd'))
                      )
                    else   
                       cg.creditlevelid 
                 end)
            end)

========================================================================================================
這是開發發過來的sql,完全一樣的SQL,在huifu2上面不到1秒能跑出來,在jsjdata0上面要跑3分鐘左右。
檢視執行計劃,可以很清晰的發現問題出在jsjdata0上面沒有走索引。creditguarantee這張表上面的列
CREATEDDATE上有一個索引NL_CREDATEDATE,在huifu2上面走了,但是在jsjdata0這裡訪問creditguarantee卻
是走的全表掃描。我第一反應是索引的統計資訊出問題了,用exec dbms_stats.gather_index_stats收集了
下索引的統計資訊,發現沒有任何效果。我先加hints再來試一試,把第一行資料改為如下寫法
select /*+index(creditlevelchange INDEX_CUSTOMERID)*/  count(0) from creditguarantee cg where 1=1
發現仍然不走索引,這就有點奇怪,這下應該是表的資料和索引有關係

jsjdata0
-- select max(CREATEDDATE) from creditguarantee 2012/2/23 17:46:01
-- select min(CREATEDDATE) from creditguarantee 2012/2/23 10:32:58

huifu2
-- select Max(CREATEDDATE) from creditguarantee  2012/2/3  16:48:56
-- select Min(CREATEDDATE) from creditguarantee  2012/1/20 14:45:52

這下原因就很簡單了,它大於的時間在表裡面根本就找不到

第一種情況:
select count(0) from creditguarantee cg where 1=1

           and cg.createddate>=to_date('2012-02-23 09:33:00','yyyy-MM-dd hh24:mi:ss')
           and cg.createddate<=to_date('2012-02-26 10:33:00','yyyy-MM-dd hh24:mi:ss')
           and 2=

再寫細點,這種就不行


第二種情況:
下面這種就可以 
select count(0) from creditguarantee cg where 1=1

           and cg.createddate>=to_date('2012-02-23 10:40:00','yyyy-MM-dd hh24:mi:ss')
           and cg.createddate<=to_date('2012-02-26 10:33:00','yyyy-MM-dd hh24:mi:ss')
           and 2=

表裡面資料時間長度的區間
   
     |-------------------------------------|
     2012/2/23 10:32:58                    2012/2/23 10:32:58


第一種情況:
|---------------------------------------------------------|
2012-02-23 09:33:00                                       2012-02-26 10:33:00


第二種情況:
               |------------------------------------------|
                2012-02-23 10:40:00                       2012-02-26 10:33:00  


總結:where後面的起始時間要大於表裡面資料的時間,如果起始時間小於表裡面的資料之後
,那個點上根本就沒有資料,那就談不上使用那個點上資料的索引了,所以強制走hints也補
會有效果。
在整個sql優化過程中,我一直把注意and 2= .....這語句的前面,通過執行計劃我發現了他們
屬於非相關聯合型操作。所以找到問題點在上面之後就不需要關注下面的SQL了

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10678398/viewspace-717236/,如需轉載,請註明出處,否則將追究法律責任。

相關文章