Wednesday, March 25, 2009

查詢與索引

每次寫了一長串SQL都免不了要做一些調整,不然使用者就每天來煩你這個慢那個慢(很哀桑),就該是跑跑execution plan的時候了。照說我們會比optimizer更清楚知道用哪個index才是對的(吧XD?),所以當index不是我們期望的那個時,可以做一些判斷與檢查。

1.          Where條件須參考到索引的欄位(前幾個欄位)

例外A: CBO執行索引快速完整掃描(Index Fast Full Scan, INDEX_FFS)的話,則可以不需參考索引的前幾個欄位。

HINT用法: /*+ INDEX_FFS([table_name] [index])*/

例外B: CBO執行Index Skip Scan(INDEX_SS)的話,也可不需參考索引的前幾個欄位。

HINT用法: /*+ INDEX_SS([table_name] [index])*/

2.          表格join的條件是否參考到索引的欄位

表格連接的三種方法中(Nested loopsHashSort merge),只有nested loops允許以inner table被用於連接的欄位做索引搜尋。

當表格是以nested loops的方法連接且join的條件有參考到索引,還須考慮表格連接的順序。Nested loopsouter table會先整個被讀取,連接inner table時才有可能使用索引做搜尋。假如索引只在outer table上有,此索引將不會被參考。(而且tableinner還是outer是由optimizer決定)

這東西我後來翻了翻書,發現可以透過(Oracle)HINT來決定join table的順序、方式、index等很多... 啊,慚愧

3.          有索引的欄位使否被函數修改/參考

索引欄位如果被函數修改或參考,此索引將不會被使用。例如做比較時資料型態不同,勢必有其中一個值需要做隱藏資料轉型,假如一個屬於索引欄位的字串被to_number()函數所參考,那此索引不會被使用。事實上做這種型態的轉換也是沒有效率的。

4.          適當的統計數值

5.          所提示的索引是否生效

HINT: /*+ IINDEX([table_name] [index])*/    //如果SQL裡的table有別名,須使用別名

假如要指定多個索引
/*+ IINDEX([table_name1] [index1]) IINDEX([table_name2] [index2])*/

Parseroptimizer可能會轉換或重寫查詢而使索引不被使用。

6.          使用view和子查詢

查詢若有view或子查詢,view會和外查詢合併,子查詢會和主查詢重組,重組後的查詢可能不會使用索引

Comments

0 Responses to "查詢與索引"

Post a Comment

Tags