Oracle9iに関する検証 その12

投稿日: 2002年6月19日

<Oracle 9iに関する検証 その12>
ペンネーム ちょびひげ

— ゴメンナサイ編 --

オブジェクトIDとは?
Oracleのオブジェクトを一意に認識する為の番号である。
前回まで検証を行なってきた、データベース・バッファ(以下、バッファ)上
のオブジェクトを見るためのX$BH表にもオブジェクトを一意に認識する為の列
が存在している。

バッファの検証では幾度となく以下のようなSQL文を発行してきた。

SQL> select
  2   o.object_name, blsiz , count(*) blocks , lru_flag , tch, state
  3  from x$bh b , dba_objects o
  4  where b.obj = o.object_id
  5    and o.object_name in ('BLOCK4','BLOCK4_IDX')
  6  group by b.blsiz, o.object_name, lru_flag, tch, state;

実は上記のSQL文には間違いがある。
と堂々と言えることでは有りませんが。。(申し訳ありません)

例えば以下のようなテーブルとインデックスが存在する。

# 最初がSUMMERで始まるオブジェクトを検索

SQL> select object_id, data_object_id, object_name from dba_objects
  2  where object_name like 'SUMMER%';

 OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- --------------------
     43064          43064 SUMMER
     43065          43065 SUMMER_IDX

SUMMER_IDXはSUMMERテーブルに張ってあるINDEXである。

OBJECT_IDとDATA_OBJECT_IDとも同じ値であることが分かる。
もちろんバッファ上の該当するオブジェクト番号も同じ値である。

SQL> select obj, count(1) from x$bh
  2  where obj in (43064,43065,43066,43067)
  3  group by obj;

       OBJ   COUNT(1)
---------- ----------
     43064         16
     43065         21

※OBJの条件に先ほど調べたオブジェクト番号と他2つを指定している。
この2つ(43066、43067)に関しては後述する

では、このオブジェクト(SUMMER)をTRUNCATEして、オブジェクト番号がどの
ように変化するかを見てみよう。

SQL> truncate table summer;

表が切り捨てられました。

SQL> select object_id, data_object_id, object_name from dba_objects
  2  where object_name like 'SUMMER%';

 OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- --------------------
     43064          43067 SUMMER
     43065          43066 SUMMER_IDX

テーブルのTRUNCATEを行うことによって、TRUNCATEしたテーブルはもちろんで
あるが、テーブルに張ってあるインデックスのDATA_OBJET_IDも変わっている
ことが分かる。

ちなみにDATA_OBJECT_IDはオブジェクトのバージョンを管理する為のIDであり、
TRUNCATEを行なうたびに番号が上がっていく。振り当てられる番号は使用され
た最大の番号(OBJECT_IDもしくはDATA_OBJECT_ID)+1である。

TRUNCATEを行なうとディクショナリの変更を行うが、実際のデータの削除は行
なわれないので、当然、ROLLBACKやREDOの情報がテーブル内の各行に対して作
成されない。そのため、データ件数が多い場合は高速であるが、古いデータを
削除するわけではないので、このようなバージョン管理が必要になってくるの
だろう。X$BH表のOBJ列はこのDATA_OBJ_IDをさしている。

面白いのはインデックスのDATA_OBJECT_IDの方が小さくなっている。内部的に
はインデックスのTRUNCATE後にテーブルをTRUNCATEしているのであろう。

また、パッケージなどはバージョンを管理する必要が無いので、DATA_OBJ_ID
列はNULL値であることが分かる。

SQL> select object_name, object_id, data_object_id, object_type from dba_objects
  2  where object_type='PACKAGE'

OBJECT_NAME                     OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
------------------------------ ---------- -------------- ------------------
HTTP_EXP                            19168                PACKAGE
HTTP_SECURITY_CASCADE               19150                PACKAGE
IFR_EXP                             19169                PACKAGE
IFR_PACKAGE                         19082                PACKAGE
INITJVMAUX                           5214                PACKAGE
IST_ENGINE90                        23788                PACKAGE
・
・

ちなみに、OBJECT_IDはDROPされない限り変わることは無い。
では最後に、TRUNCATE後のバッファの状態も見てみよう。

SQL> select obj, count(1) from x$bh
  2  where obj in (43064,43065,43066,43067)
  3  group by obj;

       OBJ   COUNT(1)
---------- ----------
     43066          1
     43067          3

先程調べたDBA_OBJECT表のOBJECT_ID列の値ではなく、DATA_OBJECT_IDの値で
あることが分かる。SQL文のOBJの条件に2つ(43066、43067)を指定している
のは、DATA_OBJ_IDが1加算されることを予測した仕掛けである。

以上、茅ヶ崎にて