Oracle DB: Oracle Exadataの性能を引き出すバッチ処理設計

本記事は私の経験によるもので、バッチ処理(AP)の設計/製造者向けの視点で書いています。全ての内容が正しいとは限りません。

Oracle Exadataは非常に高速なデータベースマシンですが、何でもかんでも高速にはなりません。バッチ処理を設計/製造する前に、Oracleが公開する資料に目を通してください。

※両リンクともPDFファイルへのリンクです。

特に設計/開発の勘所の11ページ以降は絶対に頭に入れたほうがいいです。

一括処理の4つのTips
バッチ処理の劇的な高速化を目指すために押さえておきたいこと
Tips-1:ループ処理を単一のSQLで記述
Tips-2:PL/SQLで負荷をExadataにオフロード
Tips-3:INDEX RANGE SCANよりFULL SCAN、NESTED LOOP結合よりHASH結合
Tips-4:DMLエラーハンドリングの活用

資料と被る内容もありますが、注意することを書きます。

★データ参照(INSERT時のSELECT含む)

  • とにかくFULL SCANさせる
    • FULL SCANのほうがINDEX RANGE SCANよりも早い。
    • つまりINDEXは作らない。
  • とにかくHASH JOINさせる
    • 絶対にNESTED LOOPS JOINさせない。やったら死ぬ。
    • NOT EXISTS ではなく NOT IN を使う。
  • 大量データ/テーブルのテーブル結合はしない
    • Exadataで扱うような数億数千万件のテーブルを複数結合するとコストが驚異的に跳ね上がり死ぬ。
    • データ量が大きくなる場合はオンメモリで処理できるよう絞るか分割する。
    • 何でもかんでも一度にやろうとせず、データ量を抑えるようテーブル設計、データ作成処理を設計する。
    • 共通部品としてVIEWは使わず、マテビューのように中間の共通データを作る。
  • 単純な検索は無茶苦茶早い
    • ジョブの数が増えても良いので、ジョブ1つ1つを単純なジョブにする。

★データ作成/更新

  • 基本はダイレクトパスインサートを使う
    • ダイレクトパスインサートは「INSERT /*APPEND*/ SELECT」。
    • テーブルにはNOLOGGINGを設定する。
    • データ削除はTRUNCATEを利用する。DELETEではHWMが上昇し続け、パフォーマンスが大きく劣化する。
  • バッチ(ジョブ)の設計はTRUNCATE→ダイレクトパスインサートのリレーを意識する
    • 追加も、全洗替えも、当月分のみ洗替えも、更新であっても。
    • 当月分のみ洗替は当月と過去分のテーブルを分け、データ作成時は当月分のみTRUNCATE→ダイレクトパスインサートで処理し、参照時にVIEWでUNIONする。
    • 更新は更新後のデータを別テーブル作り、最後に入れ直す。
  • どうしても更新したい場合はMERGEを使う
    • 大量データはUPDATEよりMERGEのほうがずっと早い。
  • INSERT/UPDATE/DELETEの禁止
    • INSERTは使う必要性がない。
    • UPDATE/DELETEはくっそ遅くなる。
  • カーソル禁止
    • Exadataで処理するデータ件数を考えれば絶対ダメ。
    • 条件分岐は条件ごとに処理を分割する。