Table: dbphr.p5004_phrorderreviseque


PK & index: Pharmacycode  &  quetype  &  revisedatechar  &  reviseno四個欄位建成一個PK(index)


(也就是4個欄位建成一個index)


 


Case1: 系統目前所RUNSQL:


/* Formatted on 2008/09/15 15:39 (Formatter Plus v 4.8.8 ) */


SELECT *


  FROM dbphr.p5004_phrorderreviseque


 WHERE pharmacycode = :"SYS_B_0"


Plan


SELECT STATEMENT CHOOSE Cost: 144


 


1 TABLE ACCESS FULL DBPHR.P5004_PHRORDERREVISEQUE Cost: 144 Bytes: 1,868,124 Cardinality: 45,564


條件中只寫出PK中的第一個欄位,結果走的是Full table scan.


 


Case2:


SELECT        *


  FROM dbphr.p5004_phrorderreviseque


 WHERE pharmacycode = :"SYS_B_0"


   AND quetype = :"SYS_B_1"


   AND revisedatechar = :"SYS_B_2"


   AND reviseno = :"SYS_B_0"


Plan


SELECT STATEMENT CHOOSE Cost: 3 Bytes: 41 Cardinality: 1


 


2 TABLE ACCESS BY INDEX ROWID DBPHR.P5004_PHRORDERREVISEQUE Cost: 3 Bytes: 41 Cardinality: 1


 


 


1 INDEX UNIQUE SCAN UNIQUE DBPHR.PK_P5004 Cost: 2 Cardinality: 1


全部寫出來~就會走index.


 


Case3:


SELECT        *


  FROM dbphr.p5004_phrorderreviseque


 WHERE pharmacycode = :"SYS_B_0"


   AND quetype = :"SYS_B_1"


Plan


SELECT STATEMENT CHOOSE Cost: 287 Bytes: 60,557 Cardinality: 1,477


 


1 TABLE ACCESS FULL DBPHR.P5004_PHRORDERREVISEQUE Cost: 287 Bytes: 60,557 Cardinality: 1,477


Where 條件有前兩個欄位,還是走full table scan


 


Case4:


SELECT        *


  FROM dbphr.p5004_phrorderreviseque


 WHERE pharmacycode = :"SYS_B_0"


   AND quetype = :"SYS_B_1"


   AND revisedatechar = :"SYS_B_2"


Plan


SELECT STATEMENT CHOOSE Cost: 111 Bytes: 5,043 Cardinality: 123


 


2 TABLE ACCESS BY INDEX ROWID DBPHR.P5004_PHRORDERREVISEQUE Cost: 111 Bytes: 5,043 Cardinality: 123


 


 


1 INDEX RANGE SCAN UNIQUE DBPHR.PK_P5004 Cost: 4 Cardinality: 123


Where 條件有前三個欄位, oracle抉擇後選擇走index,


但請跟case 2cost比較(cost不同,表示是兩個不同的執行計畫)


 


Case5:


SELECT        *


  FROM dbphr.p5004_phrorderreviseque


 WHERE  quetype = :"SYS_B_0"


   AND revisedatechar = :"SYS_B_1"


   AND reviseno = :"SYS_B_2"


   AND pharmacycode = :"SYS_B_0"


Plan


SELECT STATEMENT CHOOSE Cost: 3 Bytes: 41 Cardinality: 1


 


2 TABLE ACCESS BY INDEX ROWID DBPHR.P5004_PHRORDERREVISEQUE Cost: 3 Bytes: 41 Cardinality: 1


 


 


1 INDEX UNIQUE SCAN UNIQUE DBPHR.PK_P5004 Cost: 2 Cardinality: 1


將四個條件寫上,並給它亂調一下,


我們發現它還是走index,這是因為在oracle收到sql命令後內部會改寫成比較恰當的SQL敘述


(Oracle會自動有調整順序如同Case 2之敘述, 所以cost是一樣的),


所以我們認為只要有將相關的欄位寫出來,無論甚麼順序,SQL都會走index.


 


Case6:


SELECT        *


  FROM dbphr.p5004_phrorderreviseque


 WHERE  --quetype = :"SYS_B_0"


   --AND revisedatechar = :"SYS_B_1"


   --AND reviseno = :"SYS_B_2"


   --AND


pharmacycode = :"SYS_B_0"


Plan


SELECT STATEMENT CHOOSE Cost: 287 Bytes: 60,557 Cardinality: 1,477


 


1 TABLE ACCESS FULL DBPHR.P5004_PHRORDERREVISEQUE Cost: 287 Bytes: 60,557 Cardinality: 1,477


回到Case1,確定有使用到PK中的第一欄位, 加入hint: /*+ rule */ 強迫它走index


SELECT   /*+ rule */     *


  FROM dbphr.p5004_phrorderreviseque


 WHERE  pharmacycode = :"SYS_B_0"


Plan


SELECT STATEMENT HINT: RULE


 


2 TABLE ACCESS BY INDEX ROWID DBPHR.P5004_PHRORDERREVISEQUE


 


 


1 INDEX RANGE SCAN UNIQUE DBPHR.PK_P5004


 


所以結論:


目前我們ntuh系統中,有很多是多個欄位建成一個pk(也相對的有多欄位建成一個index),


如果where條件中無法將全部欄位寫出,


至少必須寫出第一個欄位並使用/*+ rule */ hint來強迫Oracle使用index來查詢.


(要不然要不要走index,全由Oracle自己的選擇)

arrow
arrow
    全站熱搜

    噗噗噗的潛水珽 發表在 痞客邦 留言(0) 人氣()