ASM を味わう ~ DISK の I/O を偏らせてみる ~ その11

投稿日: 2005年10月19日

<ASM を味わう ~ DISK の I/O を偏らせてみる ~ その11>
ペンネーム:ダーリン

前回、 ASM を使った環境では表領域の作成時に DISK Group を構成する各
DISK に比較的均等にデータファイルを分散して格納している様子を確認しま
した。ということはデータにアクセスする際の DISK I/O も均等になるのでは
!?と期待したいのですが、「ASM を味わう その9」で見たようにデータの
均等配置と同じようには I/O は分散できていないようです。

今回はこれを確認してみます。

ASM を味わう その9バックナンバー
https://old.insight-tec.com/mailmagazine/ora3/vol265.html

まず、表領域を構成するデータファイルは DISK Group 全体にわたって均等に
配置できました。次に、この表領域にテーブルを作成します。

SQL> create table tbl001 (c1 number,c2 varchar(4000)) storage (initial 1m)

Table created.


SQL> select owner, segment_name segment, segment_type seg_type
  2       , tablespace_name, extent_id ext_id, file_id, block_id blk_id
  3       , bytes, blocks
  4    from dba_extents
  5   where owner = 'DARLING'
  6     and segment_name = 'TBL001';

OWNER   SEGMENT SEG_TYPE TABLESPACE EXT_ID FILE_ID BLK_ID   BYTES BLOCKS
------- ------- -------- ---------- ------ ------- ------ ------- ------
DARLING TBL001  TABLE    TEST001         0       6      9 1048576    128

次にデータを投入します。

SQL> begin
  2  for i in 1..3840 loop
  3  insert into tbl001 (c1,c2) values (i,lpad(i,4000,'0'));
  4  end loop;
  5  commit;
  6  end;
  7  /

PL/SQL procedure successfully completed.

SQL> select count(*) from tbl001;

  COUNT(*)
----------
      3840

この時点で、EXTENTの発生状況を確認しましょう。

SQL> select segment_name segment, segment_type seg_type, tablespace_name
  2       , extent_id, block_id, bytes, blocks
  3    from dba_extents
  4   where owner = 'DARLING'
  5     and segment_name = 'TBL001'
SQL> /

SEGMENT SEG_TYPE TABLESPACE  EXTENT_ID BLOCK_ID      BYTES     BLOCKS
------- -------- ---------- ---------- -------- ---------- ----------
TBL001  TABLE    TEST001             0        9    1048576        128
TBL001  TABLE    TEST001             1      137    1048576        128
TBL001  TABLE    TEST001             2      265    1048576        128
TBL001  TABLE    TEST001             3      393    1048576        128
TBL001  TABLE    TEST001             4      521    1048576        128
.............
TBL001  TABLE    TEST001            28     3593    1048576        128
TBL001  TABLE    TEST001            29     3721    1048576        128
TBL001  TABLE    TEST001            30     3849    1048576        128

31 rows selected.

1 レコードに 4000 bytes 以上のデータを INSERT しているので、1 BLOCK に
1 レコードの割合で格納されているはずです。なので、BLOCK ID 9 から
BLOCK ID 3848 までで収まってほしかったのですが、ちょっとはみ出してしま
いました。とにかく、約 30 EXTENT 発生させました。これらは果たして各
DISK に均等に配置されているのでしょうか? つまり、約 30 EXTENT なので、
各 DISK に 10 EXTENT ずつ配置できているのでしょうか。
現状、これについてはなんともわかりません。
その手がかりになる情報はないでしょうか。 DISK の 物理 I/O 量を使って間
接的に状況を把握することは出来ないでしょうか。

試してみましょう。

上記のとおり、データを投入しました。1 BLOCK につき、1 レコードの状態で
格納されていることを確認しましょう。

SQL> analyze table tbl001 compute statistics;

Table analyzed.

SQL>  select table_name, num_rows, blocks from user_tables
  2  where table_name = 'TBL001';

TABLE_NAME  NUM_ROWS     BLOCKS
----------- -------- ----------
TBL001          3840       3840

では、この状態で検索し、どの DISK に I/O が発生するか確認します。
例えば特定のレコードを検索しそのレコードがその DISK にあるかを確認する
ことにします。もしかすると特定の条件で、ある DISK に I/O が偏るように
仕向けてもいいかもしれません。 今回はこの方法を試します。

その前に準備が必要です。全件検索してしまうと、すべての DISK に I/O が
発生してしまいますね。なので、インデックスを、別の DISK Group に作成
します。

SQL> create tablespace test001_idx datafile '+DATA' size 5m autoextend on next 1m;

Tablespace created.

SQL> alter user darling quota unlimited on test001_idx ;

User altered.

SQL> connect darling/darling

SQL> create unique index ui_tbl001 on tbl001 (c1) tablespace test001_idx;

Index created.

では、検索してみます。

特定の条件で DISK I/O を偏らせるのですが、今回は、EXTENT ごとに各 DISK
に配置されていることが予想されるので、特定の EXTENT に存在するデータ
を検索しましょう。

今回 BLOCK_SIZE = 8192 で作成している、1 MB の EXTENT には、128 レコー
ド存在するはずです。なので、128 レコードに対して、検索を行ってみます。
また、3 EXTENT ごとに同じ DISK にデータが配置されている可能性があるので、
さらに、3 EXTENT 後に格納されていると予測されるレコードも検索してみます。

SQL> declare
  2  c2_buff varchar2(4000) := null;
  3  begin
  4  for i in 1..128 loop
  5    for j in 1..10 loop
  6      select c2 into c2_buf from tbl01 where c1 = i+384*j;
  7    end loop;
  8  end loop;
  9  end;
 10  /
PL/SQL procedure successfully completed.

では、I/O はどうだったでしょうか。

検索前
~~~~~~~~~~~~~

SQL> select a.name
  2       , a.path
  3       , a.reads
  4       , a.writes
  5       , a.bytes_read
  6       , a.bytes_written
  7    from v$asm_disk a
  8       , v$asm_diskgroup b
  9   where a.group_number = b.group_number
 10     and b.name = 'DG_0001';

NAME       PATH                 READS     WRITES BYTES_READ BYTES_WRITTEN
---------- --------------- ---------- ---------- ---------- -------------
DISK_003   /dev/raw/raw5          243        854   18653184      63755264
DISK_002   /dev/raw/raw4          348        901   29921280      65025536
DISK_001   /dev/raw/raw3          345       5039    1441792      81199616

検索後
~~~~~~~~~~~~~

SQL> /

NAME       PATH                 READS     WRITES BYTES_READ BYTES_WRITTEN
---------- --------------- ---------- ---------- ---------- -------------
DISK_003   /dev/raw/raw5          275        854   23449600      63755264
DISK_002   /dev/raw/raw4          404        901   39313408      65025536
DISK_001   /dev/raw/raw3          346       5042    1445888      81211904
DISK_001  346 - 345 =   1
DISK_002  404 - 348 =  54
DISK_003  275 - 243 =  32

DISK_001 にはほとんど発生していません。v$asm_disk を検索すると、この
READS が毎回 1 上昇することを考えると、TBL001 の検索では、DISK_001
にアクセスしていないと考えてもいいでしょう。
本当は、1つの DISK にアクセスが集中すると面白かったのですが、残念なが
らそうはいきませんでした。セグメントヘッダや、ローカルエクステント管理
表領域のビットマップ管理領域もあるので、その分検索対象データをオフセッ
トするべきだったのでしょう。

来週ももう少し、I/O について見ていきます。

日本シリーズはどちらを応援しようか… 悩ましい茅ヶ崎にて