ORACLE學習筆記--效能優化FAQ。

tieshuai發表於2008-08-06

select * from v$sql_plan where hash_value = (select sql_hash_value from v$session where sid = 1111);
    其中id和parent_id表示了執行數的結構,數值最大的為最先執行

    比如

ID  PARENT_ID   
-------------   

1 0
2 1
3 2
4 3
5 4
6 3   

 

 

則執行計劃樹為
              0
              1
              2
              3
           6     4 
                  5


2.如何設定自動跟蹤
  用system登入
  執行$ORACLE_HOME/rdbms/admin/utlxplan.sql建立計劃表
  執行$ORACLE_HOME/sqlplus/admin/plustrce.sql建立plustrace角色
  如果想計劃表讓每個使用者都能使用,則
  SQL>create public synonym plan_table for plan_table;
  SQL> grant all on plan_table to public;

  如果想讓自動跟蹤的角色讓每個使用者都能使用,則
  SQL> grant plustrace to public;
  通過如下語句開啟/停止跟蹤
  SET AUTOTRACE ON |OFF | ON EXPLAIN | ON STATISTICS | TRACEONLY | TRACEONLY EXPLAIN

3.如何跟蹤自己的會話或者是別人的會話
  跟蹤自己的會話很簡單
  Alter session set sql_trace true|false
  Or
  Exec dbms_session.set_sql_trace(TRUE);

  如果跟蹤別人的會話,需要呼叫一個包
  exec dbms_system.set_sql_trace_in_session(sid,serial#,true|false)

  跟蹤的資訊在user_dump_dest 目錄下可以找到或通過如下指令碼獲得檔名稱(適用於Win環境,如果是unix需要做一定修改)
  SELECT p1.value||'\'||p2.value||'_ora_'||p.spid||'.ora' filename
  FROM
  v$process p,
  v$session s,
  v$parameter p1,
  v$parameter p2
  WHERE p1.name = 'user_dump_dest'
  AND p2.name = 'db_name'
  AND p.addr = s.paddr
  AND s.audsid = USERENV ('SESSIONID')
  最後,可以通過Tkprof來解析跟蹤檔案,如
  Tkprof 原檔案 目標檔案 sys=n

4.怎麼設定整個資料庫系統跟蹤
  其實文件上的alter system set sql_trace=true是不成功的,但是可以通過設定事件來完成這個工作,作用相等
  alter system set events
  '10046 trace name context forever,level 1';

  如果關閉跟蹤,可以用如下語句
  alter system set events
  '10046 trace name context off';

其中的level 1與上面的8都是跟蹤級別
  level 1:跟蹤SQL語句,等於sql_trace=true
  level 4:包括變數的詳細資訊
  level 8:包括等待事件
  level 12:包括繫結變數與等待事件


5.怎麼樣根據OS程式快速獲得DB程式資訊與正在執行的語句
  有些時候,我們在OS上操作,象TOP之後我們得到的OS程式,怎麼快速根據OS資訊獲得DB資訊呢?
  我們可以編寫如下指令碼:
  $more whoit.sh
  #!/bin/sh
  sqlplus /nolog 100,cascade=> TRUE);
  dbms_stats.gather_table_stats(User,TableName,degree => 4,cascade => true);

這是對命令與工具包的一些總結
  <1>、對於分割槽表,建議使用DBMS_STATS,而不是使用Analyze語句。
   a) 可以並行進行,對多個使用者,多個Table
   b) 可以得到整個分割槽表的資料和單個分割槽的資料。
   c) 可以在不同級別上Compute Statistics:單個分割槽,子分割槽,全表,所有分割槽
   d) 可以倒出統計資訊
   e) 可以使用者自動收集統計資訊
  <2>、DBMS_STATS的缺點
   a) 不能Validate Structure
   b) 不能收集CHAINED ROWS, 不能收集CLUSTER TABLE的資訊,這兩個仍舊需要使用Analyze語句。
   c) DBMS_STATS 預設不對索引進行Analyze,因為預設Cascade是False,需要手工指定為True
  <3>、對於oracle 9裡面的External Table,Analyze不能使用,只能使用DBMS_STATS來收集資訊。

6.怎麼樣快速重整索引
  通過rebuild語句,可以快速重整或移動索引到別的表空間
  rebuild有重建整個索引數的功能,可以在不刪除原始索引的情況下改變索引的儲存引數
  語法為
  alter index index_name rebuild tablespace ts_name
  storage(......);

  如果要快速重建整個使用者下的索引,可以用如下指令碼,當然,需要根據你自己的情況做相應修改
  SQL> set heading off
  SQL> set feedback off
  SQL> spool d:\index.sql
  SQL> SELECT 'alter index ' || index_name || ' rebuild '
  ||'tablespace INDEXES storage(initial 256K next 256K pctincrease 0);'
  FROM all_indexes
  WHERE ( tablespace_name != 'INDEXES'
  OR next_extent != ( 256 * 1024 )
  )
  AND wner = USER
  SQL>spool off

  另外一個合併索引的語句是
  alter index index_name coalesce

  這個語句僅僅是合併索引中同一級的leaf block,消耗不大,對於有些索引中存在大量空間浪費的情況下,有一些作用。

7.如何使用Hint提示
  在select/delete/update後寫/*+ hint */
  如 select /*+ index(TABLE_NAME INDEX_NAME) */ col1...

  注意/*和+之間不能有空格,如用hint指定使用某個索引
  select /*+ index(cbotab) */ col1 from cbotab;
  select /*+ index(cbotab cbotab1) */ col1 from cbotab;
  select /*+ index(a cbotab1) */ col1 from cbotab a;

  其中
  TABLE_NAME是必須要寫的,且如果在查詢中使用了表的別名,在hint也要用表的別名來代替表名;
  INDEX_NAME可以不必寫,Oracle會根據統計值選一個索引;
  如果索引名或表名寫錯了,那這個hint就會被忽略;

8.怎麼樣快速複製表或者是插入資料
  快速複製表可以指定Nologging選項
  如:Create table t1 nologging
  as select * from t2;

  快速插入資料可以指定append提示,但是需要注意noarchivelog模式下,預設用了append就是nologging模式的。 在archivelog下,需要把表設定程Nologging模式。
  如insert /*+ append */ into t1
  select * from t2

  注意:如果在9i環境中並設定了FORCE LOGGING,則以上操作是無效的,並不會加快,當然,可以通過如下語句設定為NO FORCE LOGGING。
  Alter database no force logging;
  是否開啟了FORCE LOGGING,可以用如下語句檢視
  SQL> select force_logging from v$database;


9.怎麼避免使用特定索引
  在很多時候,Oracle會錯誤的使用索引而導致效率的明顯下降,我們可以使用一點點技巧而避免使用不該使用的索引,如:
  表test,有欄位a,b,c,d,在a,b,c上建立聯合索引inx_a(a,b,c),在b上單獨建立了一個索引Inx_b(b)。

  在正常情況下,where a=? and b=? and c=?會用到索引inx_a,where b=?會用到索引inx_b,但是,where a=? and b=? and c=? group by b會用到哪個索引呢?在分析資料不正確(很長時間沒有分析)或根本沒有分析資料的情況下,oracle往往會使用索引inx_b。通過執行計劃的分析,這個索引的使用,將大大耗費查詢時間。

  當然,我們可以通過如下的技巧避免使用inx_b,而使用inx_a。

  where a=? and b=? and c=? group by b||'' --如果b是字元
  where a=? and b=? and c=? group by b+0 --如果b是數字

  通過這樣簡單的改變,往往可以是查詢時間提交很多倍
  當然,我們也可以使用no_index提示,相信很多人沒有用過,也是一個不錯的方法:
  select /*+ no_index(t,inx_b) */ * from test t
  where a=? and b=? and c=? group by b

  舉例:
  本來在CM_USER上有索引IDX_CM_USER4(ACC_ID)和IDX_CM_USER8(BILL_ID),可是執行如下語句的時候很慢。
  select * from CM_USER where  acc_id =1200007175
  and user_status>0 and bill_id like '13%' order by acc_id,bill_id

  用explain分析,發現執行計劃是用IDX_CM_USER8.如下查詢
  select * from user_indexes where table_name ='CM_USER' 發現IDX_CM_USER8沒有分析過。

  用下面語句執行計劃改變
  select /*+INDEX(CM_USER IDX_CM_USER4)*/* from CM_USER where  acc_id =1200007175 and user_status>0 and bill_id like '13%' order by acc_id,bill_id

  或者分析索引
  exec dbms_stats.gather_index_stats(ownname => 'QACS1',indname => 'IDX_CM_USER8',estimate_percent => 5 );
  可以發現執行計劃恢復正常。


10.Oracle什麼時候會使用跳躍式索引掃描
  這是9i的一個新特性跳躍式索引掃描(Index Skip Scan).
  例如表有索引index(a,b,c),當查詢條件為where b=?的時候,可能會使用到索引index(a,b,c),如,執行計劃中出現如下計劃:
  INDEX (SKIP SCAN) OF 'TEST_IDX' (NON-UNIQUE)

  Oracle的優化器(這裡指的是CBO)能對查詢應用Index Skip Scans至少要有幾個條件:
  <1> 優化器認為是合適的。
  <2> 索引中的前導列的唯一值的數量能滿足一定的條件(如重複值很多)。
  <3> 優化器要知道前導列的值分佈(通過分析/統計表得到)。
  <4> 合適的SQL語句
  等。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/701141/viewspace-421326/,如需轉載,請註明出處,否則將追究法律責任。

相關文章