1. 程式人生 > 其它 >Oracle 建立索引及SQL優化

Oracle 建立索引及SQL優化

Oracle 建立索引及SQL優化

一、建立資料庫索引:

索引有單列索引和複合索引之說。

建設原則:

 1、索引應該經常建在Where 子句經常用到的列上。如果某個大表經常使用某個欄位進行查詢,並且檢索行數小於總錶行數的5%。則應該考慮。

 2、對於兩表連線的欄位,應該建立索引。如果經常在某表的一個欄位進行Order By 則也經過進行索引。

 3、不應該在小表上建設索引。

優缺點:
 1、索引主要進行提高資料的查詢速度。 當進行DML時,會更新索引。因此索引越多,則DML越慢,其需要維護索引。 因此在建立索引及DML需要權衡。

2、當一個表的索引達到4個以上時,ORACLE的效能可能還是改善不了,因為OLTP系統每表超過5個索引即會降低效能,而且在一個sql 中, Oracle 從不能使用超過 5個索引

3、索引可能產生碎片,因為記錄從表中刪除時,相應也從表的索引中刪除.表釋放的空間可以再用,而索引釋放的空間卻不能再用.頻繁進行刪除操作的被索引的表,應當階段性地重建索引,以避免在索引中造成空間碎片,影響效能.在許可的條件下,也可以階段性地truncate表,truncate命令刪除表中所有記錄,也刪除索引碎片. (建立索引影響了刪除和更新操作)

建立索引:
 單一索引:Create Index On <Table_Name>(Column_Name);

 複合索引:Create Index On emp(deptno,job); —>在emp表的deptno、job列建立索引。

  select * from emp where deptno=66 and job='sals' ->走索引。

  select * from emp where deptno=66 OR job='sals' ->將進行全表掃描。不走索引

  select * from emp where deptno=66 ->走索引。

  select * from emp where job='sals' ->進行全表掃描、不走索引。

  如果在where 子句中有OR 操作符或單獨引用Job 列(索引列的後面列) 則將不會走索引,將會進行全表掃描。

  同時在Oracle裡用PL/SQL的F5可以對整個SQL查詢來判斷沒加索引前和加完索引後的用時。

索引失效的情況:
 ① Not Null/Null 如果某列建立索引,當進行Select * from emp where depto is not null/is null。 則會是索引失效。
 ② 索引列上不要使用函式,SELECT Col FROM tbl WHERE substr(name ,1 ,3 ) = 'ABC' 或 SELECT Col FROM tbl WHERE name LIKE '%ABC%' 而 SELECT Col FROM tbl WHERE name LIKE 'ABC%' 會使用索引。

 ③ 索引列上不能進行計算SELECT Col FROM tbl WHERE col / 10 > 10 則會使索引失效,應該改成SELECT Col FROM tbl WHERE col > 10 * 10

 ④ 索引列上不要使用NOT ( != 、 <> )如:SELECT Col FROM tbl WHERE col ! = 10 應該改成:SELECT Col FROM tbl WHERE col > 10 OR col < 10 。

二、關於SQL 效能優化

(一)ORACLE 效能優化主要方法
⑴硬體升級(CPU、記憶體、硬碟):

 CPU:在任何機器中CPU的資料處理能力往往是衡量計算機效能的一個標誌,並且ORACLE是一個提供並行能力的資料庫系統,如果執行佇列數目超過了CPU處理的數目,效能就會下降;
 記憶體:衡量機器效能的另外一個指標就是記憶體的多少了,在ORACLE中記憶體和我們在建資料庫中的交換區進行資料的交換,讀資料時,磁碟I/O必須等待物理I/O操作完成,在出現ORACLE的記憶體瓶頸時,我們第一個要考慮的是增加記憶體,由於I/O的響應時間是影響ORACLE效能的主要引數;
 網路條件:NET*SQL負責資料在網路上的來往,大量的SQL會令網路速度變慢。比如10M的網絡卡和100的網絡卡就對NET*SQL有非常明顯的影響,還有交換機、集線器等等網路裝置的效能對網路的影響很明顯,建議在任何網路中不要試圖用3個集線器來將網段互聯。

⑵版本及引數設定

⑶應用程式設計(框架、呼叫方式---原始碼)

 程式設計中的一個著名定律是20%的程式碼用去了80%的時間;
 兩種方式優化:原始碼的優化和SQL語句的優化。原始碼的優化在時間成本和風險上代價很高;另一方面,原始碼的優化對資料庫系統性能的提升收效有限。
 DBMS處理查詢計劃的過程是這樣的:在做完查詢語句的詞法、語法檢查之後,將語句提交給DBMS的查詢優化器,優化器做完代數優化和存取路徑的優化之後,由預編譯模組對語句進行處理並生成查詢規劃,然後在合適的時間提交給系統處理執行,最後將執行結果返回給使用者。 

⑷SQL 語句優化:

當Oracle資料庫拿到SQL語句時,其會根據查詢優化器分析該語句,並根據分析結果生成查詢執行計劃。
也就是說,資料庫是執行的查詢計劃,而不是Sql語句。
查詢優化器有rule-based-optimizer(基於規則的查詢優化器) 和Cost-Based-optimizer(基於成本的查詢優化器)。
其中基於規則的查詢優化器在10g版本中消失。
對於規則查詢,其最後查詢的是全表掃描。而CBO則會根據統計資訊進行最後的選擇。

①先執行From ->Where ->Group By->Order By,所以儘量避免全表掃。

②執行From 字句是從右往左進行執行。因此必須選擇記錄條數最少的表放在右邊。  

③對於Where字句其執行順序是從後向前執行、因此可以過濾最大數量記錄的條件必須寫在Where子句的末尾,而對於多表之間的連線,則寫在之前。因為這樣進行連線時,可以去掉大多不重複的項。  

④SELECT子句中避免使用()ORACLE在解析的過程中, 會將’’ 依次轉換成所有的列名, 這個工作是通過查詢資料字典完成的, 這意味著將耗費更多的時間.但是在count(*)和count(1)的執行中不需要遵守上述內容,速度經過我測試是相同的。

⑤用UNION替換OR(適用於索引列)

  union:是將兩個查詢的結果集進行追加在一起,它不會引起列的變化。 由於是追加操作,需要兩個結果集的列數應該是相關的,並且相應列的資料型別也應該相當的。union 返回兩個結果集,同時將兩個結果集重複的項進行消除。 如果不進行消除,用UNOIN ALL.

通常情況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將造成全表掃描. 注意, 以上規則只針對多個索引列有效.
如果有column沒有被索引, 查詢效率可能會因為你沒有選擇OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引.

  高效:
  SELECT ID , NAME
  FROM LOCATION
  WHERE ID = 1
  UNION
  SELECT ID , NAME
  FROM LOCATION
  WHERE NAME = “SUQI356”

  低效:
  SELECT ID , NAME
  FROM LOCATION
  WHERE ID = 1 OR NAME = “SUQI356”
  如果你堅持要用OR, 那就需要返回記錄最少的索引列寫在最前面.

⑥用EXISTS替代IN、用NOT EXISTS替代NOT IN和用(+)比用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’)

⑦ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫在最後的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連線查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表 。

⑧避免使用HAVING子句, HAVING 只會在檢索出所有記錄之後才對結果集進行過濾,這個處理需要排序、總計等操作; 如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷.

⑨儘可能使用varchar代替char,因為變長欄位儲存空間小,在一個相對較小的欄位內搜尋效率要高。

⑩使用臨時表來儲存
————————————————
版權宣告:本文為CSDN博主「小個子的奧特曼」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/suqi356/article/details/79281770