ファイル番号とブロック番号からオブジェクト情報を得たい。
このような簡単な要求が実際には性能については大変なことになってしまいます。例えば、次のような待機イベントがあるとしてみます。
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