每次寫了一長串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 loops、Hash、Sort merge),只有nested loops允許以inner table被用於連接的欄位做索引搜尋。
當表格是以nested loops的方法連接且join的條件有參考到索引,還須考慮表格連接的順序。Nested loops的outer table會先整個被讀取,連接inner table時才有可能使用索引做搜尋。假如索引只在outer table上有,此索引將不會被參考。(而且table是inner還是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])*/
Parser或optimizer可能會轉換或重寫查詢而使索引不被使用。
6. 使用view和子查詢
查詢若有view或子查詢,view會和外查詢合併,子查詢會和主查詢重組,重組後的查詢可能不會使用索引
Post a Comment