データベースバッファの検証

データベースバッファに関することで、前から気になってたことがあったので検証してみた。

10万件のテーブルから1件のレコードをテーブルフルスキャンによって取得した際に、データベースバッファ上に載る対象となるのは、
10万件か、1件のみなのか?

フルスキャンで10万件を取得した場合

データベースバッファの状態を確認(freeが空き領域)

SQL> select status,count(*) from v$bh group by status ;

STATUS       COUNT(*)
---------- ----------
cr                 13
free             1431
xcur             1556

10万件のレコードを取得

SQL> select * from test;

100000行が選択されました。

統計
----------------------------------------------------------
        335  recursive calls
          0  db block gets
       7292  consistent gets
        626  physical reads
          0  redo size
    4860720  bytes sent via SQL*Net to client
      73698  bytes received via SQL*Net from client
       6668  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
     100000  rows processed

データベースバッファ確認

SQL> select status,count(*) from v$bh group by status ;

STATUS       COUNT(*)
---------- ----------
cr                 15
free              771
xcur             2214

約700程度使っていることに。

10万件のテーブルからフルスキャンで1件のみを取得した場合

まず、データベースバッファをクリア。
Oracle10gなら「alter system flush buffer_cache」でクリアすることが可能だが、
Oracle9iでの検証のため、インスタンスを再起動することに。。
( 「alter system flush shared_pool」ならあるが、これは共有プールをクリアするもので
データベースバッファはクリアされない)
再起動後、データベースバッファ確認。

SQL>  select status,count(*) from v$bh group by status ;

STATUS       COUNT(*)
---------- ----------
cr                 13
free             1434
xcur             1553

10万件のテーブルからフルスキャンで1件のみ取得

SQL> select * from test where test_num = 10000;

統計
----------------------------------------------------------
        335  recursive calls
          0  db block gets
        669  consistent gets
        626  physical reads
          0  redo size
        721  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
          1  rows processed

データベースバッファ確認。

SQL> select status,count(*) from v$bh group by status ;

STATUS       COUNT(*)
---------- ----------
cr                 14
free              776
xcur             2210

最初と同様に700程度使っている。よって、1件のみ取得した場合でも
10万件が対象となっていることがわかる。
念のためINDEXを利用した場合についても検証してみる。

INDEXを利用して、10万件から1件を取得した場合

INDEX作成。

SQL> create unique index test_num_idx on test(test_num);

索引が作成されました。

再起動後、データベースバッファ確認。

SQL> select status,count(*) from v$bh group by status ;

STATUS       COUNT(*)
---------- ----------
cr                 13
free             1115
xcur             1872

INDEXを利用して1件取得。

SQL> select * from test where test_num = 10000;

統計
----------------------------------------------------------
        364  recursive calls
          0  db block gets
         53  consistent gets
          5  physical reads
          0  redo size
        721  bytes sent via SQL*Net to client
        372  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
          1  rows processed

データベースバッファ確認。

SQL> select status,count(*) from v$bh group by status ;

STATUS       COUNT(*)
---------- ----------
cr                 13
free             1110
xcur             1877

5しか使っていない。
ってことは、INDEXをうまく利用すれば、物理アクセスも減らせるし、
バッファ上に無駄なデータも置かなくてもよく、メリット多いってことか。