轉載:http://www.javashuo.com/article/p-gsotoauf-md.html
分析和優化的基本步驟以下:
一、若是是SQL語句的寫法問題,咱們能夠經過在不更改業務邏輯的狀況下改寫SQL來加以解決;java
二、若是是沒必要要的全表掃描/排序而致使了目標SQL的性能問題,咱們能夠經過創建合適的索引(包括函數索引、位圖索引等)來加以解決;
三、若是是表或者索引的不良設計致使的目標SQL的性能問題,咱們能夠經過從新設計表/索引,從新組織表裏的數據來加以解決;
四、若是上述調整措施都失效,咱們能夠考慮用並行來縮短目標SQL的執行時間;
五、若是上述調整措施、包括並行都失效,咱們還能夠在聯繫實際業務的基礎上更改目標SQL的執行邏輯,甚至不執行目標SQL,這是最完全的優化。sql
Oracle數據庫優化的方法
一、減小訪問數據庫的次數。
二、不要讓數據庫作得太多。
(1)SELECT子句中避免使用' ':ORACLE在解析的過程當中,會將' '依次轉換成全部的列名, 這個工做是經過查詢數據字典完成的,這意味着將耗費更多的時間。
(2)sql語句用大寫的:由於oracle老是先解析sql語句,把小寫的字母轉換成大寫的再執行。另外,在java代碼中儘可能少用鏈接符「+」鏈接字符串!
(3)使用表的別名(Alias):當在SQL語句中鏈接多個表時, 請使用表的別名並把別名前綴於每一個Column上。這樣一來,就能夠減小解析的時間並減小那些由Column歧義引發的語法錯誤。
(4) 用>=替代>:
高效: SELECT FROM EMP WHERE DEPTNO >=4
低效: SELECT FROM EMP WHERE DEPTNO >3
二者的區別在於, 前者DBMS將直接跳到第一個DEPT等於4的記錄然後者將首先定位到DEPTNO=3的記錄而且向前掃描到第一個DEPT大於3的記錄。
(5) 用EXISTS替代IN、用NOT EXISTS替代NOT IN:在許多基於基礎表的查詢中,爲了知足一個條件,每每須要對另外一個表進行聯接.在這種狀況下, 使用EXISTS(或NOT EXISTS)一般將提升查詢的效率。 在子查詢中,NOT IN子句將執行一個內部的排序和合並。不管在哪一種狀況下,NOT IN都是最低效的 (由於它對子查詢中的表執行了一個全表遍歷)。 爲了不使用NOT IN ,咱們能夠把它改寫成外鏈接(Outer Joins)或NOT EXISTS。
例子:
(高效)SELECT FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(6)用EXISTS替換DISTINCT:例如:
低效: SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO
高效: SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
(7)儘可能用UNION-ALL 替換UNION ( if possible)
當SQL語句須要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 而後在輸出最終結果前進行排序。
低效:SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ’31-DEC-95’
UNION SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ’31-DEC-95’
高效: SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ’31-DEC-95’
UNION ALL SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = ’31-DEC-95’
(7) 避免在索引列上使用NOT:一般,避免在索引列上使用NOT, NOT會產生在和在索引列上使用函數相同的影響。 當Oracle」遇到」NOT,就會中止使用索引轉而執行全表掃描。
(8)用索引提升效率:索引是表的一個概念部分,用來提升檢索數據的效率,ORACLE使用了一個複雜的自平衡B-tree結構。 一般,經過索引查詢數據比全表掃描要快。當Oracle找出執行查詢和Update語句的最佳路徑時,Oracle優化器將使用索引。一樣在聯結多個表時使用索引也能夠提升效率. 另外一個使用索引的好處是,它提供了主鍵(primary key)的惟一性驗證。一般, 在大型表中使用索引特別有效。 雖然使用索引能獲得查詢效率的提升,可是咱們也必須注意到它的代價。 索引須要空間來存儲,也須要按期維護, 每當有記錄在表中增減或索引列被修改時,索引自己也會被修改。這意味着每條記錄的INSERT , DELETE , UPDATE將爲此多付出4 , 5 次的磁盤I/O 。由於索引須要額外的存儲空間和處理,那些沒必要要的索引反而會使查詢反應時間變慢。按期的重構索引是有必要的。
Oracle創建索引的建議
一、表的主鍵、外鍵必須有索引;Oracle中外鍵不添加索引會引發死鎖。當刪除父表指定記錄時,子表會添加表級鎖,另外一個進程刪除父表記錄(即便是不一樣記錄)時,會形成子表死鎖。當對子表的外鍵列添加索引後,死鎖被消除,由於這時刪除父表記錄不須要對子表加表級鎖。
二、常常與其餘表進行鏈接的表,在鏈接字段上應該創建索引;
三、索引應該建在選擇性高的字段上。例如:表示性別的數據列,因爲只有男女兩種值,就屬於選擇性低;
四、索引應該建在小字段上,對於大的文本字段甚至超長字段,不要建索引;
五、複合索引的創建須要進行仔細分析,儘可能考慮用單字段索引代替:
A、正確選擇複合索引中的主列字段(第一個字段),通常是選擇性較好的字段;
B、複合索引的幾個字段是否常常同時以AND方式出如今WHERE子句中?單字段查詢是否極少甚至沒有?若是是,則能夠創建複合索引;不然考慮單字段索引;
C、若是既有單字段索引,又有這幾個字段上的複合索引,通常能夠刪除複合索引;
六、頻繁進行數據操做的表,不要創建太多的索引;
七、刪除無用的索引,避免對執行計劃形成負面影響;
總之,索引的創建必須慎重,對每一個索引的必要性都應該通過仔細分析,要有創建的依據。由於太多的索引與不充分、不正確的索引對性能都毫無益處:在表上創建的每一個索引都會增長存儲開銷,索引對於插入、刪除、更新操做也會增長處理上的開銷。另外,過多的複合索引,在有單字段索引的狀況下,通常都是沒有存在價值的;相反,還會下降數據增長刪除時的性能,特別是對頻繁更新的表來講,負面影響更大。
在大多數狀況下,複合索引比單字段索引好.複合索引比單字段索引的效率高,可是,複合索引比單字段索引的內容原理複雜,複合索引有兩個重要原則須要把握:前綴性和可選性.若是糊里糊塗的濫用複合索引,效果拔苗助長。
以例子來講明,例子以下:
假設在員工表(EMP)的(ENAME,JOB,MGR)3個字段上建了一個索引,例如索引名叫IDX_1.3個字段分別爲員工姓名,工做和所屬經理號。而後,寫以下一個查詢語句,並不斷進行查詢條件和次序的排列組合,例如:
[sql] view plain copy
<span style="font-family:Microsoft YaHei;">SELECT FROM EMP WHERE ENAME = 'A' AND JOB = 'B' AND MGR = 3 ;
SELECT FROM EMP WHERE JOB = 'B' AND ENAME = 'A' AND MGR = 3 ;
SELECT FROM EMP WHERE MGR = 3 AND ENAME = 'A' AND JOB = 'B' ;
SELECT FROM EMP WHERE MGR = 3 AND JOB = 'B' AND ENAME = 'A' ;
SELECT * FROM EMP WHERE JOB = 'B' AND MGR = 3 AND ENAME = 'A' ; </span>
回答問題:在各類條件組合狀況下,剛纔建的索引(IDX_1) 是用仍是不用?也就是說對EMP表的訪問是全表掃描仍是按索引(IDX_1)訪問?
答案是 : 上述語句中只要有ENAME='A'條件,就能用上索引(IND_1),而不是全表掃描(這就是複合索引的前綴性).數據庫