oracle數據庫優化

1、數據庫級的優化sql

1.  nccm_chargedetail 表分區   1499萬 半年數據量 (解決百萬級,千萬級數據量)
   partition by list (BURYEAR)
   (
     partition P_2013  values ('2013')
     tablespace T_2013
     pctfree 10
     initrans 1
     maxtrans 255
     storage (
              initial 3114M
              next 1M
              minextents 1
              maxextents unlimited
              )
    );
    
 2. 索引 (index)
    假設表中有100000行,而sql要讀取表中20%的行,也就是20000;再作個假設,若是行大小
    約80字節,那麼塊大小爲8kb的塊則大約100行,這說明表大約1000個塊。那麼經過索引讀取
    的話, 大約20000個TABLE ACCESS BY ROWID
    操做來執行查詢,那麼須要處理200000個塊,但整個表才1000個塊。
    在這種狀況下,全表掃描要比用索引高效。
  
    索引使用規則:一般對於小表,Oracle建議經過全表掃描進行數據訪問,對於大表則應該
    經過索引以加快數據查詢,固然若是查詢要求返回表中大部分或者所有數據,那麼全表掃
    描可能仍然是最好的選擇。
    像查詢nccm_clinicsub 門診報銷表中某個家庭的全部報銷單據,有什麼理由不用索引呢 ?
    select * from nccm_clinicsub h where h.famid='4115252521010313' and h.buryear='2013';
  
    索引須要空間來存儲,也須要按期維護,
    每當有記錄在表中增減或索引列被修改時, 索引自己也會被修改.
    這意味着每條記錄的INSERT , DELETE , UPDATE將爲此多付出4 , 5 次的磁盤I/O .
    由於索引須要額外的存儲空間和處理,那些沒必要要的索引反而會使查詢反應時間變慢。數據庫

3. 鏈接池 (Connection Pool機制)
   鏈接會話的三種狀態 active inactive killed
   合理的配置鏈接池: 最小鏈接數、最大鏈接數、閒置鏈接數、回收鏈接時間
  
 
4. 視圖 (view)  nccm_mtp
   視圖是基於一個表或多個表或視圖的邏輯表,自己不包含數據,經過它能夠對
   表裏面的數據進行查詢和修改。視圖基於的表稱爲基表。視圖是存儲在數據字
   典裏的一條select語句。 經過建立視圖能夠提取數據的邏輯上的集合或組合。
  
   視圖的優勢:
  
   ① 對數據庫的訪問,由於視圖能夠有選擇性的選取數據庫裏的一部分。
   ② 用戶經過簡單的查詢能夠從複雜查詢中獲得結果。
   ③ 維護數據的獨立性,試圖可從多個表檢索數據。
   ④ 對於相同的數據可產生不一樣的視圖。
  
   dic_code_medical   dic_code_treat  dic_code_ops
   create or replace view nccm_mtp as  sql;
  
5. 臨時表  
    create global temporary table 臨時表名 on commit preserve|delete rows ;
    用preserve時就是SESSION級的臨時表,用delete就是TRANSACTION級的臨時表;
  
   ① 循環SQL:系統中有不少相似的sql循環執行,效率很低
   ② 多表關聯:  利用臨時表簡化有太多表關聯的複雜SQL
   ③ 若是某個數據集會重複屢次使用的狀況下建議使用臨時表
   ④ 臨時表做爲複雜查詢條件的中間結果用於主查詢
  
   nccm_pro_prov_report_03oracle


6. 控制碎片
   碎片(fragmentation)是對一組非鄰接的數據庫對象的描述。碎片意味着在執行數據庫
   的功能時要耗費額外的資源(磁盤I/O,磁盤驅動的循環延遲,動態擴展,連接的塊等)
   ,並浪費大量磁盤空間。當兩個或多個數據對象在相同的表空間中,會發生區間交叉。
   在動態增加中,對象的區間之間再也不相互鄰接。爲了消除區間交叉將靜態的或只有小增
   長的表放置在一個表空間中,而把動態增加的對象分別放在各自的表空間中。
   在create table、、create index、create tablespace、create cluster時,
   在storage(指定對象的存儲參數)子句中的參數的合理設置,能夠減小碎片的產生。
  
      ① 字典表、變更少的表   用表空間1;
      ②天天都動態增加的表用 表空間二、三、4等;
      ③storage參數的意義;
     
     
2、sql級優化
 
1.  oralce優化器
    執行計劃:   在執行sql語句時,Oracle須要執行不少步驟。在每一步中,Oracle或者從
    數據庫中讀取數據,或者爲用戶提交sql語句準備數據。這些Oracle在執行sql語句時使用
    的步驟的集合叫作執行計劃。
   
    oracle優化器:在執行sql語句時,oracle優化器都要對sql語句進行解析,獲得一個執行計劃。
    由於解析操做比較浪費系統資源,致使系統性能降低。因此解析完sql語句後,都要將解析獲得
    的執行計劃保存在內存中。若是再次執行該sql,就不須要解析了,直接從內存中獲取其執行計劃。
    因此再次提醒儘可能減小訪問數據庫的次數以及sql語句的執行次數,不要在客戶機器上開開pl/sql
    不關,一直佔用資源。更甚着有用for update鎖表的(致使程序短期掛掉)。查看錶的時候不要用
    編輯表,而是用查看錶。
   
    Hints(提示):基於代價的優化器是很聰明的,在絕大多數狀況下它會選擇正確的優化器,減輕
    了DBA的負擔。但有時它也聰明反被聰明誤,選擇了不好的執行計劃,使某個語句的執行變得奇
    慢無比。此時就須要DBA進行人爲的干預,告訴優化器使用咱們指定的存取路徑或鏈接類型生成
    執行計劃,從而使語句高效的運行。
    例如,若是咱們認爲對於一個特定的語句,執行全表掃描要比執行索引掃描更有效,則咱們就
    能夠指示優化器使用全表掃描。在Oracle中,是經過爲語句添加 Hints(提示)來實現干預優化
    器優化的目的。
   
    建立執行計劃表:sqlplus nccm/nccm@nccm
     sql> @D:\app\Administrator\product\11.1.0\db_2\RDBMS\ADMIN\utlxplan.sql
   
    查看執行計劃表的結構:desc plan_table; 
    id  步驟編號 operation 所執行內部操做名稱 optimizer 優化器當前的模式 cost 操做成本
     cardinality 訪問行數 bytes 訪問的字節數 
   
    查看執行計劃: explain plan for select * from nccm_hossubsidy;
   
    查看執行計劃表的數據:    select * from plan_table;
   
    查看格式化的數據:
    select lpad('', 2 * (level - 1)) || operation || '' || options || '' ||
       object_name || '' || decode(id, 0, 'Cost=' || position) "Query Plan"
    from plan_table  connect by prior id = parent_id;
    刪除表中的數據:delete from plan_table;
    最優的查詢plan_table方式:select * from table(DBMS_XPLAN.display);
    最最優的查詢方式:用pl/sql的F5
   
   
   
2.  FROM/WHERE子句中的鏈接順序
    經測試只在基於規則的優化器中有效;而oracle默認的是ebo模式;
    查看當前優化器模式:
    select name,value from v$parameter where name ='optimizer_mode';
    alter system set optimizer_mode=Rule scope=spfile;
    關閉實例 卸載數據庫: shutdown或者shut immediate;
    開啓實例 打開數據庫: connect /as sysdba; startup;
    Rule:          不用多說,即走基於規則的方式。
    Choolse:       這是咱們應觀注的,默認的狀況下Oracle用的即是這種方式。指的是當一個
    表或或索引有統計信息,則走CBO的方式,若是表或索引沒統計信息,表又不是特別的小,並且
    相應的列有索引時,那麼就走索引,走RBO的方式。
    First Rows:    它與Choose方式是相似的,所不一樣的是當一個表有統計信息時,它將是以最快
    的方式返回查詢的最早的幾行,從整體上減小了響應時間。
    All Rows:      也就是咱們所說的Cost的方式,當一個表有統計信息時,它將以最快的方式返
    回表的全部的行,從整體上提升查詢的吞吐量。沒有統計信息則走基於規則的方式。
   
    select * from nccm_hossubsidy h ,nccm_joinperson j where h.personid=j.personid;
    select * from nccm_joinperson j ,nccm_hossubsidy h where h.personid=j.personid;
    select * from nccm_clinicsub c where c.famid='4115250528010234' 
    and c.birthday='19000101';
    select * from nccm_clinicsub c where c.birthday='19000101' and
    c.famid='4115250528010234' ;
    自從oracle添加優化器功能後,已經沒有效果了; 雖然加載條件與表的順序依然是從右到左。
   
   
   
3.  索引的恰當使用
    where子句中對索引字段計算運用函數、類型轉換等會致使索引的失效!
    select * from nccm_clinicsub c where substr(c.famid,1,16)='4115250528010234'
     and c.birthday='19000101';
    select * from nccm_clinicsub c where c.famid||'01'='411525052801023401'
    and c.birthday='19000101';
   
4.  在程序中儘可能多使用COMMIT
    nccm_savePayfeeinfo  農合繳費過程  沒有及時的commit
   
5.  見過最奇葩的sql語句:
    select c,name,c.orgcode,c.diagdate from nccm_clinicsub c
    where c.famid='4115250528010234' and c.buryear='2013';
    循環遍歷:
    select p.pointegername from nccm_pointegerorg p where p.pointegercode=orgcode;
          app

6.  in、exists、group by的正確使用
    group by的having和where
    select orgcode, h.orglevel, sum(h.factsub)
     from nccm_hossubsidy h
    where h.orglevel > 3
    group by h.orgcode, h.orglevel
   
    select orgcode, h.orglevel, sum(h.factsub)
    from nccm_hossubsidy h
    group by h.orgcode, h.orglevel
    having h.orglevel > 3
   
    經測試not in/exists 無效
    select *
    from nccm_hossubsidy h
    where h.villcode in (select t.villcode
                        from nccm_hossubsidy t
                       where t.villcode = '4115252521');
    select *
    from nccm_hossubsidy h
    where exists (select 1
          from nccm_hossubsidy t
         where t.villcode = h.villcode
           and t.villcode = '4115252521');
    select *
    from nccm_chargedetail c
    where c.billcode not in
       (select h.billcode
          from nccm_hossubsidy h
         where h.billcode = 'Z0000000000000000011');函數

    select *
    from nccm_chargedetail c
    where not exists (select 1
          from nccm_hossubsidy h
         where h.billcode = c.billcode
           and h.billcode = 'Z0000000000000000011');
          
     爲何exists與in的效果同樣呢???   
    在oracle 9i中,默認提供是基於選擇的優化器,即當有分析數據時,採用基於成本的優化方式,
    沒有則仍採用基於規則的查詢方式,這樣優化模式下基本等同於基於規則或者基於成本。在10g之
    後的版本,默認都是以基於成本的方式進行,這時候,oracle會先找出可能的執行方式,而後計算
    出每一個執行計劃的成本,再選擇以較低成本的方式進行計算,這樣子在對in和exists的分析中,這
    兩種寫法會相互轉換,那個統計的成本信息低則會選擇那種方式。固然因爲oracle的成本信息並不
    是全量統計得出來的結果,也會有必定的偏差,再統計信息是須要人工(或定時)去執行統計的,
    若是操做大量數據後,沒有進行統計,誤差也會很大。
   
    批量插入數據優化:
    常規的插入方法:
       循環loop 10000:
           insert into table (a,b,c,d);
       end;
    批量插入的方法:
       循環loop 100:
          v_sql:='insert into table select a,b,c,d from dual';
            循環loop 100:
                v_sql:=v_sql||'union all select a,b,c,d from dual';
            end;
          execute immediate v_sql;
       end;
    批量插入僅僅完成100次插入,效率要遠遠高於10000次的常規插入。
   
   
   
    儘可能不要使用‘*’以及用select max(clicode) from nccm_clinicsub c            
    oop

相關文章
相關標籤/搜索