Oracle 建立索引及SQL優化


數據庫索引:

  索引有單列索引,復合索引之說。

  如某表的某個字段有主鍵約束和唯一性約束,則oracle會自動在相應的約束列上建議問一索引。數據庫索引主要進行提高訪問速度。

  (如樓層索引,進來先看索引能快速定位到要找的樓層房間)

  建設原則:

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

    2、對於兩表鏈接的字段,應該建立索引。如果經常在某表的一個字段進行order by  則也經過進行索引。

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

  優缺點:

    1、索引主要進行提高數據的查詢速度。當進行DML時,會更新索引。因此索引越多,則DML越慢,其需要維護索引。因此在創建索引及DML時需要權衡。

  創建索引:

    單一索引:create <index_type> Index <index_name> on <table_name>(column_name)。

    復合索引:create <index_type> Index cbs_Index on thr_cbsglb(ssxm,ywzgbm)。

    select * from thr_cbsglb where ssxm= 66 and ywzgbm= ywzgbm-->走索引

    select * from thr_cbsglb where CBS = 66 or ywzgbm= 45 -->不走索引

    select * from thr_cbsglb where ssxm= 66 -->走索引

    select * from thr_cbsglb where ywzgbm= 45-->不走索引

    如果where子句中有or操作符或單獨引用ywzgbm列(索引列的后面列)則將不會走索引,將會進行全盤掃描。

Sql優化:

  當oracle數據庫拿到sql語句時,其會根據查詢優化器分析改語句,並根據分析結果生成查詢執行計划。也就是說數據庫時執行的查詢計划,而不時sql語句。

  查詢優化器有rule-based-optimizer(基於規則的查詢優化器)和Cost-Based-optimizer(基於成本的查詢優化器)。

  其中基於規則的查詢優化器在10g版本中消失。對於規則查詢,其最后查詢的是全表掃描。而CBO則會根據統計信息進行最后的選擇。

  1、先執行from -> where -> group by -> order by 

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

  3、對於where子句其執行順序是從后往前執行、因此可以過濾大數量記錄的條件必須寫在where子句的末尾。而對於多表之間的連接,則寫在之前,因為這樣連接時,

    可以去掉大多不重復的項。

  4、select子句中避免使用(*),oracle在解析的過程中,會將(*)依次轉換成所有的列名,這個工作時通過數據字典完成的,這意味着將耗費更多的時間。

  5、索引失效情況:

    ① not null/null 如果某列建立索引,當進行select * from thr_cbsglb where ssxm is not null/ is null 則會索引失效。

    ② 索引列上不要使用函數,select ssgs from thr_cbsglb where substr(cbsmc,1,3) = '12隊'  或則 select ssgs from thr_cbsglb where cbsmc like '%12隊%',前者失效后者會使用。

    ③ 索引上不能進行計算, select ssgs from thr_cbsglb where ssxm / 10 > 10 則會使索引失效,應改成select  ssgs from thr_cbsglb where ssxm > 10 * 10。

    ④ 索引列上不要使用not(!=、<>)如:select ssgs from thr_cbsglb where ssxm != 10,應改成select ssgs from thr_cbsglb where ssxm > 10 or ssxm < 10。

  6、用union替換or(適用於索引列)

      union:是將使將兩個查詢的結果集並行到一起,它不會引起列的變化。由於是追加操作,需要兩個結果集的列數應該是相關的,並且相應列的數據類型也因該相同的。union返回

       兩個結果集,同時將兩個結果集的重復項進行取消,如果不取消則用union all。

      通常情況下,用union替換where子句中的or將會起到較好的效果,隊索引列使用or將造成全表掃描。注意:以上規則只針對多個索引列有效。

      如果有column沒有被索引,查詢效率可能會因為沒有選擇or而降低。(thr_cbsglb_id、cbsmc都建有索引)

      高效:

      select thr_cbsglb_id,ssxm,cbsmc from thr_cbsglb where thr_cbsglb_id = 10

      union

      select thr_cbsglb_id,ssxm,cbsmc from thr_cbsglb where cbsmc = '12隊'

      低效:

      select thr_cbsglb_id,ssxm,cbsmc from thr_cbsglb where thr_cbsglb_id = 10 or cbsmc = '12隊'

      如果堅持要用or,那就需要將返回記錄最少的索引列寫在最前面。

  7、用exists代替 in、用not exists代替 not in

     在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表驚醒連接,在這種情況下使用exists或者not exists通常將提高查詢的效率。

     在子查詢中,not in 子句將執行一個內部的排序和合並,無論在哪種情況下,not in都是最低效的(因為它對子查詢中的表執行了一個全表遍歷)。

     為了避免使用not in,可以把它改寫為外連接(outer joins)或not exists。

     高效:

     select * from THR_AQJCBZK where exists(select 'x'  from thr_yjfl where thr_yjfl.yjfl_id = thr_aqjcbzk.yjfl_id and zjid like '12%')

    低效:

    select * from THR_AQJCBZK where yjfl_id in(select yjfl_id  from thr_yjfl where zjid like '12%')

    

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM