1、對於像狀態之類的列,不是很多的,就可以加位圖索引,對於唯一的列,就加唯一索引,其余的創建普通索引。
2、盡量不要使用select * 這樣的查詢,指定需要查詢的列。
3、使用hits select /*+index(索引名稱) index(索引名稱)*/ supply_id from CSS_SUPPLY where ...
4、將表table在線重定義為分區表,在name列上使用hash分區或者range分區
5、如果是exedata平台,不要用索引,盡量少用hint;
6、用並行;
---------------------
| Oracle的索引 |
---------------------
Oracle提供大量的索引選項,使用索引的目的是為了加快查詢速度、減少I/O操作和消除磁盤排序,那么在何種情況下建立索引才能發揮索引的作用呢?通常情況下建立索引的規則[2]可描述如下: (1) 表的主鍵和外鍵必須有索引; (2) 對經常與其他表進行連接的表的連接字段應該建立索引; (3) 經常出現在Where子句中的字段應該建立索引(尤其是數據量較大的表的字段); (4) 選擇性高的字段應該建立索引; 索引的選擇性是指索引列里不同值的數目與表中記錄數的比。如果表中有1000個記錄,表索引列有950個不同的值,那么這個索引的選擇性就是0.95。最好的可能性選擇是1.0,依據非空值列的唯一索引,通常其選擇性為1.0。 (5) 小字段應該建立索引,對於較長的文本字段甚至超長字段,不要建索引; (6) 復合索引的建立需要經過仔細分析,盡量考慮用單字段索引代替; ① 正確選擇復合索引中主列字段,一般是選擇“選擇性”較好 的字段; ② 復合索引的幾個字段是否經常同時以AND方式出現在Where子句中?單字段的查詢是否極少甚至沒有?如果以上兩種情況或兩者之一,則應該建立復合索引,否則考慮單字段索引; ③ 如果復合索引中包含的字段經常單獨出現在Where子句中,則分解為多個單字段索引; ④ 復合索引所包含的字段一般不要超過3個,否則需要仔細考慮其必要性; ⑤ 如果既有單字段索引,又有包含這幾個字段的復合索引,一般可以刪除復合索引; ⑥ 建立復合索引的特殊情況:如果表中的數據相當穩定且字段不多,可以考慮充分索引一個表,即創建一個復合索引,它包括所有在查詢期間通常會被選擇的列,查詢所要求的所有數據可以通過索引訪問提供,避免了索引掃描隨后的任何表訪問。
(7) 頻繁進行插入、刪除操作的表,不要建立過多索引; (8) 刪除無用索引,避免對執行計划造成負面影響;
以上是一些建立索引時較為普遍的判斷依據。太多的索引與不充分、不正確的索引對性能都毫無益處,因為在表上建立的每個索引都會增加存儲開銷,索引對於插入、刪除、更新操作也會增加處理上的開銷。另外,過多的復合索引,在有單字段索引的情況下,一般都是沒有存在價值的;相反,還會降低數據增加刪除時的性能,特別是對頻繁更新的表來說,負面影響更大。
---------------------
| SQL語句的優化 |
---------------------
正確地使用索引,可以理使用資源,使得數據的查詢速度加快。但是,建立索引之后,並非就意味着查詢時的速度得到了提高,這時還需要有良好的SQL語句進行支持,才能使得查詢中利用索引從而提高查詢的速度。下面將對如何在SQL語句中利用索引來提高查詢速度進行一下分析。
(1) IS NULL 與 IS NOT NULL 不能用null作索引,任何包含null值的列都將不會被包含在索引中。即使索引有多列的情況下,只要這些列中有一列含有null,該列就會從索引中排除。也就是說如果某列存在空值,即使對該列建索引也不會提高性能。任何在where子句中使用is null或is not null的語句優化器是不允許使用索引的。
(2) 聯接列 對於有聯接的列,即使最后的聯接值為一個靜態值,優化器是不會使用索引的。比如下面的sql語句 select * from oil where oil_name||' '||oil_id ='勝坨 shengtuo';
要查詢油田為“勝坨 shengtuo”的油田的數據,假設在oil_id列已經建了索引,此sql語句雖然也能實現正確的查詢,但系統優化器對基於oil_id創建的索引卻沒有使用。如果改為以下的sql語句 select * from oil where oil_name ='勝坨’and oil_id= ‘shengtuo';
Oracle系統就可以采用基於oil_id創建的索引。
(3) 帶通配符(%)的like語句
同樣以上面的例子來看這種情況。目前的需求是這樣的,要求在oil表中查詢名稱中包含勝坨的油。可以采用如下的查詢SQL語句:select * from employee where oil_name like '%勝坨%'; 在以上sql語句中通配符(%)在搜尋詞首出現,所以Oracle系統不使用oil_id的索引。不過在很多情況下可能無法避免這種情況,但是需要了解的是如此使用通配符會降低查詢速度。不過當通配符出現在字符串的其它位置時,優化器就可以利用索引了,例如以下的查詢就可以利用索引: select * from employee where oil_name like '勝坨%';
(4) Order by語句 order by語句決定了Oracle如何將返回的查詢結果排序。order by語句對要排序的列沒有什么特別的限制,也可以將函數加入列中(像聯接或者附加等)。任何在order by語句的非索引項或者有計算表達式都將降低查詢速度。 仔細檢查order by語句以找出非索引項或者表達式,它們會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應絕對避免在order by子句中使用表達式。
(5) NOT 在查詢中,我們經常在where子句使用一些邏輯表達式,如大於、小於、等於以及不等於等等,也會用到and(與)、or(或)以及not(非)。NOT可用來對任何邏輯運算符號取反,比如... where not (oil_id='shengtuo') 如果要使用NOT,則應在取反的短語前面加上括號,並在短語前面加上not運算符。not運算符包含在另外一個邏輯運算符中,這就是不等於(<>)運算符。也可以說,即使不在查詢where子句中顯式地加入not詞,not仍在運算符中。
看下面兩條sql語句:
select * from oil where productoil <>3000; select * from oil where productoil <3000 or productoil >3000;
雖然這兩種查詢的結果一樣,但是第二種查詢方案會比第一種查詢方案更快些。第二種查詢允許Oracle對productoil列使用索引,而第一種查詢則不能使用索引。
(6) IN和EXISTS
在查詢中,我們也經常會用到兩列進行比較的情況,最簡單的方法是在where句子中使用子查詢,而這種子查詢一般有兩種形式。 一種是利用in操作符:... where column in (select * from ...where ...); 另一種是使用exist操作符:... where exists (select 'X' from ...where ...);
對於這兩種格式的子查詢語句,一般都會使用第一種是用in操作符的查詢,因為這種語句比較容易些,也很直觀,但實際上卻是第二種格式的子查詢效率會更高。在Oracle中可以將幾乎所有的in操作符子查詢改寫為使用exists的子查詢。 第二種格式中,子查詢以‘select 'X'’開始。運用exists子句不管子查詢從表中抽取什么數據它只查看where子句的特點,這樣優化器就不必遍歷整個表而僅根據索引就可完成工作(這里假定在where語句中使用的列存在索引)。相對於IN子句來說,exists使用相連子查詢,構造起來要比in子查詢困難一些。 通過使用exists,Oracle系統會首先檢查主查詢,然后運行子查詢直到找到第一個匹配項,這就節省了時間。Oracle系統在執行in子查詢時,首先執行子查詢,並將獲得的結果列表存放在一個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以后再執行主查詢。這也就是使用exists比使用in通常查詢速度快的原因。
---------------------
| 臨時表 |
---------------------
目前大部分使用Oracle作為數據庫的系統數據量都比較龐大,在使用時我們經常會用到有多個表關聯的情況,而且這些表大部分都比較龐大,但是當進行關聯的時候卻發現某一個表或幾個表關聯之后得到的結果集很小而且查詢這個結果集的速度也非常快,那么這時候我們就可以考慮在Oracle中創建“臨時表”。這樣在工程中多次用到這些數據時直接查詢臨時表的速度要快很多,而當用完之后表中的數據就沒用了,而且Oracle的臨時表創建之后基本不占用表空間。 與使用永久表不同,添加或者更改臨時表中的數據並不會生成重做日志條目,但是,它會生成撤銷日志條目。永久表與臨時表之間的另一項區別是片段的分配。臨時表使用臨時片段,並且在表中實際插入數據之前,不會向表分配臨時片段。
ORACLE數據庫系統的臨時表有兩種,一種是事務型臨時表,一種是會話型臨時表。事物型臨時表是當一個事務結束時清空臨時表的內容;而會話型臨時表就當一個會話中斷或者被重新連接時數據表的內容就會清空了。ORACLE數據庫在清除臨時表時,只清除數據,而不清楚臨時表的本身。ORACLE還提供了一種更加細分的事務型臨時表。一個會話中,可能有多個事務。也就是說,ORACLE清空臨時型數據表的時間更加細膩,可以根據同一個會話中的不同事務來清空臨時表。另外還要說明的一點就是,ORACLE的會話型臨時中的內容對於各個用戶來說,內容都是獨立的。具體的說,就是各個用戶在會話的過程中,都可以往一張臨時表中存儲數據;但是用戶查詢臨時表中的數據的時候,只能夠查詢到自己所創建的內容,而不能看到其他用戶所增加的記錄。這對於臨時表的安全性來說,是非常有保障的。 臨時表也有局限性,比如:
(1) 臨時表只在當前連接內有效;
(2) 臨時表不建立索引,所以如果數據量比較大或進行多次查詢時,不推薦使用;
(3) 數據處理比較復雜的時候時較快,反之視圖快點。
---------------------
| 總結 |
---------------------
綜上所述,在進行簡單查詢時,充分利用索引,並合理的優化SQL語句來有效的利用索引,可以減少響應時間。而在工程中利用臨時表減少數據的訪問量、提高數據庫操作的效率,從而減少響應時間。但是以上的優化方法都是作為參考用的,優化必須隨着系統應用情況的變化和數據量的變化而調整,靈活地采取優化手段才能有效地提高系統效率。