Tuesday, July 7, 2009

ファイル番号とブロック番号からオブジェクト情報得る

ファイル番号とブロック番号からオブジェクト情報を得たい。

このような簡単な要求が実際には性能については大変なことになってしまいます。例えば、次のような待機イベントがあるとしてみます。

   1: WAIT #6: nam='db file scattered read' ela= 438472 file#=6 block#=2641 blocks=8
   2: WAIT #6: nam='db file scattered read' ela= 1039 file#=6 block#=833 blocks=8 obj#=90054 tim=878243950382
   3: WAIT #6: nam='db file scattered read' ela= 835 file#=10 block#=22961 blocks=8 obj#=90054 tim=878243957168
   4: WAIT #6: nam='db file scattered read' ela= 815 file#=11 block#=7409 blocks=8 obj#=90054 tim=878243966696
   5: ...

P1(ファイル番号)とP2(ブロック番号)からオブジェクトの名前を得たいとします。どうすればいいでしょうか。一番一般的な方法は次のようにDBA_EXTENTSビューを問い合わせて見るのです。でも、その性能はとても悪いです。

   1: UKJA@ukja102> ed which_obj
   2:  
   3: /*
   4: define __FILE = &1
   5: define __BLOCK = &2
   6: 
   7: select segment_name
   8: from dba_extents
   9: where file_id = &__FILE
  10:   and &__BLOCK between block_id and block_id + blocks - 1
  11:             and rownum = 1
  12: ;
  13: 
  14: set echo on
  15: 
  16: */
  17:  
  18: UKJA@ukja102> @which_obj 6 2641
  19:  
  20: SEGMENT_NAME
  21: --------------------
  22: T1_N1
  23:  
  24: Elapsed: 00:02:43.84
  25:  
  26: Statistics
  27: ----------------------------------------------------------
  28:        4676  recursive calls
  29:           2  db block gets
  30:     4077424  consistent gets
  31:        6492  physical reads
  32:           0  redo size
  33:         418  bytes sent via SQL*Net to client
  34:         400  bytes received via SQL*Net from client
  35:           2  SQL*Net roundtrips to/from client
  36:           5  sorts (memory)
  37:           0  sorts (disk)
  38:           1  rows processed

この性能問題を解決ために、いくつの代案が具現されています。 1)DBA_EXTENTSビューに対して集計表を作る、2)X$BHビューをとても速く問い合わせする、3)ブロックダンプをしてそれからオブジェクトIDを取る。

3番目の方法を応用すれば、次のように完全に自動的にオブジェクトIDを迅速に取ることができます。

   1: UKJA@ukja102> ed which_obj2
   2:  
   3: /*
   4: define __FILE = &1
   5: define __BLOCK = &2
   6: 
   7: alter system dump datafile &__FILE block &__BLOCK;
   8: 
   9: set serveroutput on
  10: 
  11: declare
  12:     v_dba        varchar2(100);
  13:     v_type    varchar2(100);
  14:     v_obj_id        number;
  15:     v_obj_name    varchar2(100);
  16: begin
  17:     for r in (select column_value as t from table(get_trace_file1)) loop
  18:         if regexp_like(r.t, 'buffer tsn:') then
  19:             dbms_output.put_line('------------------------------------------------');
  20:             v_dba := regexp_substr(r.t, '[[:digit:]]+/[[:digit:]]+');
  21:             dbms_output.put_line(rpad('dba = ',20)|| v_dba);
  22:         end if;
  23: 
  24:         if regexp_like(r.t, 'type: 0x([[:xdigit:]]+)=([[:print:]]+)') then
  25:             v_type := substr(regexp_substr(r.t, '=[[:print:]]+'), 2);
  26:             dbms_output.put_line(rpad('type = ',20)|| v_type);
  27:         end if;
  28: 
  29:         if regexp_like(r.t, 'seg/obj:') then
  30:             v_obj_id := to_dec(substr(regexp_substr(r.t,
  31:                             'seg/obj: 0x[[:xdigit:]]+'), 12));
  32:             select object_name into v_obj_name from all_objects
  33:                 where data_object_id = v_obj_id;
  34:             dbms_output.put_line(rpad('object_id = ',20)|| v_obj_id);
  35:             dbms_output.put_line(rpad('object_name = ',20)|| v_obj_name);
  36:         end if;
  37: 
  38:         if regexp_like(r.t, 'Objd: [[:digit:]]+') then
  39:             v_obj_id := substr(regexp_substr(r.t, 'Objd: [[:digit:]]+'), 7);
  40:             select object_name into v_obj_name from all_objects
  41:                 where data_object_id = v_obj_id;
  42:             dbms_output.put_line(rpad('object_id = ',20)|| v_obj_id);
  43:             dbms_output.put_line(rpad('object_name = ',20)|| v_obj_name);
  44:         end if;
  45: 
  46:     end loop;
  47: 
  48:     dbms_output.put_line('------------------------------------------------');
  49: 
  50: end;
  51: /
  52: 
  53: */
  54:  
  55: UKJA@ukja102> @which_obj2 6 2641
  56: old   1: alter system dump datafile &__FILE block &__BLOCK
  57: new   1: alter system dump datafile 6 block 2641
  58:  
  59: System altered.
  60:  
  61: Elapsed: 00:00:00.01
  62: ------------------------------------------------
  63: dba =               6/2641
  64: type =              FIRST LEVEL BITMAP BLOCK
  65: object_id =         90055
  66: object_name =       T1_N1
  67: ------------------------------------------------
  68: PL/SQL procedure successfully completed.
  69:  
  70: Elapsed: 00:00:00.04

2分以上の遅い作業が0.1秒以下の効率的な作業に変わったことをみています。

No comments:

Post a Comment