Oracle Real Application Clusterの検証 その8

<Oracle Real Application Clusterの検証 ~その8~>
ペンネーム ダーリン

— RAC環境でのチューニング —

本日も”しとしと”か”じとじと”かわかりませんが雨が続いています。
皆さんいかがお過ごしでしょうか。

先週は、データ登録時のインスタンス間のインデックスブロック競合を回避
する方法として、node_noというインスタンスを特定するカラムをインデック
スの先頭に追加することを検討しました。インサート時の同一ブロック競合
は防げるはずです。
で、インデックスの構成を変更したので、インデックス本来の目的である検
索側の処理に影響を与えていないか確認する必要があります。その結果、そ
れまでインデックス検索されていたテーブルが全件検索に変わっていること
が判明しました。

検索側の処理が遅くなっては、本末転倒なので、取り敢えずヒント句を追加
してインデックス検索を行わせたところ、元通りとはいきませんでしたがテー
ブルの全件検索は回避できそうであることがわかりました。

(先週の資料)

SQL> select /*+ index(logtbl1 idx_logtbl1) */ *
  2  from logtbl1
  3  where ins_date > sysdate -1 and ins_date <= sysdate;

6666行が選択されました。

実行計画
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=29 Card=832 Bytes=215488)
1    0   FILTER
2    1     TABLE ACCESS (BY INDEX ROWID) OF 'LOGTBL1' (Cost=29 Card=832 Bytes=215488)
3    2       INDEX (FULL SCAN) OF 'IDX_LOGTBL1' (NON-UNIQUE) (Cost=26 Card=832)

統計
----------------------------------------------------------
0  recursive calls
0  db block gets
1624  consistent gets
0  physical reads
0  redo size
926564  bytes sent via SQL*Net to client
5387  bytes received via SQL*Net from client
446  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
6666  rows processed

ところで、上記の実行計画からインデックスのFULL SCANが実行されているこ
とがわかります。 Oracle 9iからインデックス・スキップ・スキャンと言う
機能があります。ご存知の方も多いとおもいます。複合インデックスの先頭
カラムをwhere句に記述していない場合でも、そのインデックスを使用でき
る機能です。

これを試してみましょう。

SQL> select /*+ index_ss(logtbl1 idx_logtbl1) */ *
2  from logtbl1
3  where ins_date > sysdate -1 and ins_date <= sysdate;

6666行が選択されました。

実行計画
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=14 Card=832 Bytes=215488)
1    0   FILTER
2    1     TABLE ACCESS (BY INDEX ROWID) OF 'LOGTBL1' (Cost=14 Card=832 Bytes=215488)
3    2       INDEX (SKIP SCAN) OF 'IDX_LOGTBL1' (NON-UNIQUE) (Cost=11 Card=1)

統計
----------------------------------------------------------
0  recursive calls
0  db block gets
1938  consistent gets
0  physical reads
0  redo size
928575  bytes sent via SQL*Net to client
5387  bytes received via SQL*Net from client
446  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
6666  rows processed

んーーーー。微妙ですね。
consistent getsが幾分大きくなっています。

ちょっと、SQL TRACEを見てみましょう。
こんな具合です。

********************************************************************************
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch      446      0.29       0.30          0       1624          0        6666
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      448      0.29       0.30          0       1624          0        6666

Rows     Row Source Operation
-------  ---------------------------------------------------
6666  FILTER  (cr=1624 r=0 w=0 time=285041 us)
6666   TABLE ACCESS BY INDEX ROWID LOGTBL1 (cr=1624 r=0 w=0 time=278196 us)
6666    INDEX FULL SCAN IDX_LOGTBL1 (cr=1047 r=0 w=0 time=259729 us)(object id 7584)

********************************************************************************
********************************************************************************
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch      446      0.09       0.11          0       1938          0        6666
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total      448      0.09       0.11          0       1938          0        6666

Rows     Row Source Operation
-------  ---------------------------------------------------
6666  FILTER  (cr=1938 r=0 w=0 time=86471 us)
6666   TABLE ACCESS BY INDEX ROWID LOGTBL1 (cr=1938 r=0 w=0 time=79785 us)
6666    INDEX SKIP SCAN IDX_LOGTBL1 (cr=1361 r=0 w=0 time=57261 us)(object id 7584)

********************************************************************************

おー。確かに取得ブロック数はインデックス・スキップ・スキャンを使ったと
きの方が多いようですが、むしろ処理時間はこちらの方が速いですね。この理
由については、またの機会に調査するとして、少しでも早いほうを使ってみま
しょう。

今回は、SQL文にヒント句を追加しましたが、ANALYZEを実行しておけば
OPTIMIZERの判断で、インデックス・スキップ・スキャンを自動的に選択す
ることもあります。

今週はこの辺で、、、
ではまた来週。
夢見の悪い今日この頃。 茅ヶ崎にて