12 従来型パス・ロードおよびダイレクト・パス・ロード

SQL*Loaderには、従来のパス・ロード方法とダイレクト・パス・ロード方法を使用してデータをロードするオプションがあります。

関連トピック

12.1 データのロード方法

SQL*Loaderでは、従来型パス・ロードまたはダイレクト・パス・ロードのいずれかを使用してデータをロードできます。

従来型パス・ロードでは、SQL INSERT文を実行してOracle Databaseに表を移入します。ダイレクト・パス・ロードでは、Oracleデータ・ブロックをフォーマットしてからデータ・ブロックを直接データ・ファイルに書き込むことによって、Oracle Databaseのオーバーヘッドを大幅に削減します。ダイレクト・パス・ロードでは、データベース・リソースに対して他のユーザーとの競合が発生しないため、ディスク速度に近い速度でデータをロードできます。

ロードする表は、すでにデータベースに存在する必要があります。SQL*Loaderでは、表は作成されません。すでにデータが含まれているか、または空である既存の表にロードされます。

ロードには次の権限が必要です。

  • ロードする表についてのINSERT権限。
  • REPLACEオプションまたはTRUNCATEオプションを使用して古いデータを削除してから新しくデータをロードする場合には、ロードする表についてのDELETE権限。

12.2 ROWID列のロード

従来型パス・ロードおよびダイレクト・パス・ロードの両方において、ROWID列のテキスト値を指定できます。

これは、SELECT ROWID FROM table_nameの処理の実行時に取得するテキストと同じです。ROWIDの文字列解釈は、表内の列に対してはROWID型に変換されます。

12.3 従来型パス・ロード

SQL*Loaderの従来のパス・ロードの概要、従来のパス・ロードを使用してデータを渡すタイミングと方法、この機能に適用される制限を学習します。

12.3.1 従来型パス・ロード

従来型パス・ロード(デフォルト)では、SQL*LoaderはSQL INSERT文とバインド配列バッファを使用して、データをデータベース表にロードします。

SQL*Loaderで従来型パス・ロードを実行する場合、バッファ・リソースに関して他のすべてのプロセスと同等の処理が行われるため、競合が発生します。このメソッドを使用すると、ロードにかなりの時間がかかります。また、SQL文が生成され、Oracle Databaseに渡されてから実行されるため、さらにオーバーヘッドが発生します。

挿入が発生すると、常に、Oracle Databaseで空き領域のあるブロック(ディスク内に散在して、部分的に書込み可能なブロック)が検索され、そこにデータが書き込まれます。通常のデータベース使用の場合はそれほどでもありませんが、このメソッドは大量データのロード速度を大幅に低下させることがあります。

12.3.2 従来型パスを使用する場合

ダイレクト・パス・ロードではなく従来型のパス・ロードを使用する場合を決定するには、ユースケース・シナリオのオプションを確認します。

ロードを高速にするには、従来型パス・ロードよりダイレクト・ パス・ロードを使用します。ただし、ダイレクト・パス・ロードにはいくつかの制限があるため、従来型パス・ロードを使用することが必要な場合もあります。次のような場合には、従来型パス・ロードを使用します。

  • ロードと並行して索引付き表にアクセスする場合、またはロードと並行して索引なしの表に挿入または更新を行う場合。

    ノート: ダイレクト・パス・ロード(パラレル・ロードは除く)を使用するには、SQL*Loaderに、表への排他的書込み権限と、すべての索引への排他的読取り権限および書込み権限が必要です。

  • データをクラスタ表にロードする場合。

    理由: ダイレクト・パス・ロードでは、クラスタ表に対するロードをサポートしていません。

  • 比較的少数の行を索引付きの大きな表にロードする場合。

    理由: ダイレクト・パス・ロードでは、既存の索引は新しい索引キーとマージするときにコピーされます。既存の索引が非常に大きく、新しいキーの数が非常に少ない場合は、索引をコピーする時間が、ダイレクト・パス・ロードで節約できる時間を相殺してしまうことがあります。

  • 参照整合性制約および列チェック整合性制約のある大きな表に、比較的少数の行をロードする場合。

    理由: これらの制約は、ダイレクト・パスでロードした行には適用できないため、ロードが継続している行には適用されません。そして、ロードが完了した時点で表全体に適用されます。表が非常に大きく、新しい行の数が少ない場合は、この処理にかかる時間が節約した時間より多くなる可能性があります。

  • レコードのロード時に、次のような状況でレコードが拒否されることを確認する場合。

    • レコードの挿入でOracleエラーが発生する場合

    • レコードが間違ってフォーマットされたため、SQL*Loaderでフィールドの境界を見つけられない場合。

    • レコードが制約に違反した場合、または一意の索引を非一意にしようとした場合

12.3.3 単一パーティションの従来型パス・ロード

SQL*Loaderでは、INSERT文のパーティション拡張構文を使用します。

従来型パス・ロードでは、SQL INSERT文を使用します。ただし、従来型パスで単一パーティションに対してロードする場合は、SQL*Loaderで次のような形式のINSERT文のパーティション拡張構文を使用します。

INSERT INTO TABLE T PARTITION (P) VALUES ... 

OracleカーネルのSQLレイヤーでは、挿入される行が指定のパーティションに対応するかどうかを判断します。行が指定のパーティションに対応しない場合、その行は拒否され、そのことを示すエラー・メッセージがSQL*Loaderログ・ファイルに記録されます。

12.4 ダイレクト・パス・ロード

SQL*Loaderのダイレクト・パス・ロードの概要、ダイレクト・パス・ロードを使用してデータを渡すタイミングと方法、この機能に適用される制限を学習します。

12.4.1 SQL*Loaderダイレクト・パス・ロードについて

SQL*Loaderダイレクト・パス・ロード・オプションでは、ダイレクト・パスAPIを使用して、サーバーのロード・エンジンにロードされるデータを渡します。

SQL*Loaderのダイレクト・パス・ロード機能を使用すると、バインド配列がバッファに書き込まれるのではなく、SQLのINSERT文を使用してOracle Databaseに渡されます。ダイレクト・パス・ロードでは、ダイレクト・パスAPIを使用して、ロードするデータがサーバー内のロード・エンジンに渡されます。ロード・エンジンは、渡されたデータから列配列構造体を作成します。

ダイレクト・パス・ロード・エンジンは、列配列構造体を使用してOracle Databaseのデータ・ブロックをフォーマットし、索引キーを作成します。新しくフォーマットされたデータベース・ブロックが直接データベースに書き込まれます(ホスト・プラットフォームが非同期I/Oをサポートしている場合、非同期書込みを使用して1つのI/O要求に対して複数のブロックを書き込むことができます)。

内部的には、フォーマットされたブロック用に複数のバッファが使用されます。ホスト・プラットフォームで非同期I/Oが可能な場合は、あるバッファに書き込んでいる間に1つ以上のバッファへの書込みが行われます。この場合、I/Oを伴う処理がオーバーラップするため、ロード・パフォーマンスが向上します。

12.4.2 シノニムへのロード

ダイレクト・パス・ロードでは、SQL*Loaderを使用して表のシノニムにデータをロードできます。ただし、そのシノニムが表または単純な表のビューを直接指している必要があります。

以下の制限に注意してください。

  • ユーザー定義の型またはXMLデータのいずれかを持つ表にビューが存在する場合、ダイレクト・パス・モードは使用できません。
  • ダイレクト・パス・モードでは、SQL式を含むSQL*Loader制御ファイルを使用してビューをロードすることはできません。

12.4.3 ダイレクト・パスのフィールド・デフォルト

ダイレクト・パス・ロードを使用する場合、データベースに定義されているデフォルトの列指定は使用できません。

デフォルト値を設定するフィールドに対しては、DEFAULTIF句を使用して指定する必要があります。DEFAULTIF句が指定されておらず、フィールドがNULLである場合は、NULL値がデータベースに挿入されます。

12.4.4 整合性制約

ダイレクト・パス・ロード時には、すべての整合性制約が適用されます。ただし、すべての制約が同時に適用されるとはかぎりません。

NOT NULL制約は、SQL*Loaderのロード中に適用されます。これらの制約に従っていないレコードは拒否されます。

ロード中およびロード後に、UNIQUE制約が施行されます。UNIQUE制約に違反するレコードは拒否されます(制約違反が検出されると、そのレコードはメモリー内で使用不可になります)。

他の行または表に依存する整合性制約(参照制約など)は、ダイレクト・パス・ロード実行前に使用禁止になります。そのため、ロード後に再び使用可能にする必要があります。REENABLEを指定すると、SQL*Loaderにより、これらの制約はロード終了時に自動的に使用可能に戻されます。制約が再び使用可能になった時点で、表全体(すべての行)に対してチェックが行われます。このチェックでエラーが見つかった行は、指定されたエラー・ログに書き込まれます。

12.4.5 ダイレクト・パスを使用する場合

ダイレクト・パス・ロードでSQL*Loaderを実行する必要がある状況を学習します。

ビュー、フィールド・デフォルトまたは整合性制約によって制限されていない場合は、次の状況でダイレクト・パス・ロードを使用する必要があります。

  • 短時間で大量のデータをロードする必要がある場合。ダイレクト・パス・ロードによって、大量のデータを高速ロードし、索引付けできます。表が空であるかどうかにかかわらず、データをロードできます。

  • 最大のパフォーマンスを得るため、データをパラレルでロードする場合。

12.4.6 単一パーティションのダイレクト・パス・ロードでの制限

単一パーティションのダイレクト・パス・ロードを使用する場合は、ダイレクト・パス・ロードに指定するパーティションが追加の要件を満たす必要があります。

前述の制限に加え、単一のパーティションをロードするときには次の制限があります。

  • パーティションのある表に、グローバル索引が定義されていないこと。
  • パーティションのある表に対して、参照制約およびCHECK制約が使用禁止であること。
  • トリガーが使用禁止であること。

12.4.7 ダイレクト・パス・ロード使用上の制限

ダイレクト・パス・ロード方式を使用するには、表およびセグメントが特定の要件を満たしている必要があります。一部の機能は、ダイレクト・パス・ロードでは使用できません。

ダイレクト・パス・ロードを使用するには、次の条件を満たしている必要があります。

  • ロードする表はクラスタ化できません。

  • ロードする表は、INSERTでアクティブなOracle Virtual Private Database (VPD)ポリシーを含むことができません。

  • ロードするセグメントは、未処理のアクティブなトランザクションを含むことができません。

    アクティブなトランザクションを確認するには、MONITOR TABLEというOracle Enterprise Managerコマンドを使用して、ロードする表のオブジェクトIDを検索します。次に、MONITOR LOCKコマンドを使用して、表にロックがかけられているかどうか調べます。

  • Oracle9iより前のOracle Databaseリリースでは、クライアントとサーバーが同じリリースである場合のみ、SQL*Loaderのダイレクト・パス・ロードを実行できます。この制限は、Oracle9iのデータを以前のOracle Databaseリリースにダイレクト・パス・ロードできないことも意味しています。たとえば、ダイレクト・パス・ロードを使用して、Oracle Database 9iリリース1 (9.0.1)からOracle 8i (8.1.7)のOracle Databaseにデータをロードすることはできません。

    Oracle Database 9i以降では、クライアントとサーバーのリリースが異なる場合にも、SQL*Loaderのダイレクト・パス・ロードを実行できます。ただし、両方がOracle Database 9iリリース1 (9.0.1)以降で、クライアントのリリースは、サーバーのリリースと同じかそれ未満である必要があります。たとえば、Oracle Database 9iリリース1 (9.0.1)データベースからOracle Database 9iリリース2 (9.2)へのダイレクト・パス・ロードを実行できます。ただし、Oracle Database 10gからOracle Database 9iリリースへのデータのロードに、ダイレクト・パス・ロードを使用することはできません。

次の機能は、ダイレクト・パス・ロードでは使用できません。

  • BFILE列のロード

  • ロード時のCREATE SEQUENCEの使用。これは、ダイレクト・パスがINSERT文を生成しないため、ダイレクト・パス・ロードでは、次の値をフェッチするSQLが生成されないことが理由です。

12.4.8 ダイレクト・パス・ロードのメリット

通常、ダイレクト・パス・ロードは従来型パス・ロードを使用するよりも高速です。

ダイレクト・パス・ロードは、従来型パス・ロードよりも処理が高速です。その理由は次のとおりです。

  • 一部使用中の部分ブロックを使用しないため、空きブロックを検索するための読取り処理が不要で、書込みも少なくなります。

  • SQL*LoaderではSQL INSERT文を実行する必要がないため、Oracle Databaseでの処理負荷が軽減されます。

  • 表と索引をロード開始時にロックするようにOracle Databaseに要求し、ロード完了時にロック解除を要求します。従来型パス・ロードでは、行配列ごとにOracle Databaseコールを1回発行して、SQL INSERT文を処理します。

  • マルチ・ブロックの非同期I/Oを使用してデータベース・ファイルに書き込みます。

  • ダイレクト・パス・ロード中に、プロセスは、Oracle Databaseのバッファ・キャッシュを使用するのではなく、そのプロセス独自の書込みI/Oを実行します。この処理方法により、他のOracle Databaseユーザーとの競合を最少にします。

  • SORTED INDEXESオプションを指定すると、使用システムまたはインストール環境に固有の高性能ソート・ルーチンを使用して、データを事前にソートしておくことができます。

  • ロードするように指定した表が空の場合、事前ソート・オプションにより索引作成のソート段階とマージ段階が排除されます。索引は、データの挿入時に作成されます。

  • インスタンス障害からのリストアに、REDOログ・ファイル・エントリは必要ありません。したがって、次の場合は、ロード時のログを記録する時間は不要です。

    • Oracle Databaseで、SQL NOARCHIVELOGパラメータが使用可能な場合

    • SQL*LoaderのUNRECOVERABLE句が使用可能な場合

    • ロードするオブジェクトのSQL NOLOGGINGパラメータが設定されている場合

12.4.9 単一パーティションまたはサブパーティションのダイレクト・パス・ロード

ダイレクト・パスで単一パーティションに対してロードする場合、SQL*LoaderではLOAD文のパーティション拡張構文を使用します。

パーティション表またはサブパーティション表の単一パーティションをロードするとき、SQL*Loaderによって行がパーティション化され、SQL*Loader制御ファイルに指定されたパーティションまたはサブパーティションにマップされていない行はすべて拒否されます。ロードされるデータのパーティションまたはサブパーティションに対応するローカル索引パーティションは、SQL*Loaderによってメンテナンスされます。単一パーティションまたはサブパーティションのダイレクト・パス・ロードでは、グローバル索引はメンテナンスされません。ただし、ダイレクト・パスで単一パーティションに対してロードする場合、SQL*Loaderでは次のような形式のLOAD文のパーティション拡張構文を使用します。

LOAD INTO TABLE T PARTITION (P) VALUES ... 

LOAD INTO TABLE T SUBPARTITION (P) VALUES ... 

パーティション表またはサブパーティション表の1つのパーティションをロードしている間も、その表の他のパーティションに対してはDML操作やダイレクト・パス・ロードを行うことができます。

ダイレクト・パス・ロードはデータベース処理を最小化しますが、ロードを初期化してから終了するために、ロードの開始時と終了時にOracle Databaseに対する何回かのコールが必要です。また、ロードの初期化中に特定のDMLロックが必要です。ロードが完了すると、これらのDMLロックは解除されます。ロード中に次の操作が発生します。

  • 索引キーが作成されてソートされます
  • 領域管理ルーチンが、必要に応じて新しいエクステントを取得し、データ・セーブポイントの上限(最高水位標)を調整するために使用されます。

データの保護の詳細は、「データ・セーブを使用したデータ損失の防止」を参照してください。

12.4.10 パーティション表またはサブパーティション表のダイレクト・パス・ロード

パーティション表またはサブパーティション表へロードする場合は、SQL*Loaderによって、行がパーティション化され、索引(索引もパーティション化できます)がメンテナンスされます。

パーティション表またはサブパーティション表のダイレクト・パス・ロードは、パーティションまたはサブパーティションの多い表の場合、非常に多くのリソースを使用することに注意してください。

ノート:

複数のパーティションに対してダイレクト・パス・ロードを実行する場合に領域エラーが発生すると、ロードは直前のコミット・ポイントにロールバックされます。コミット・ポイントが存在しない場合、ロード全体がロールバックされます。これによって、領域エラー後に検出されたデータが異なるパーティションに書き込まれることがなくなります。

ROWSパラメータを使用して、コミット・ポイントの頻度を指定できます。ROWSパラメータが指定されていない場合、ロード全体がロールバックされます。

12.4.11 ダイレクト・パス・ロード時のデータ変換

SQL*Loaderのダイレクト・パス・ロード時には、サーバー側ではなくクライアント側でデータ変換が発生します。

クライアント側のデータ変換が意味しているのは、データベース初期化パラメータ・ファイルのNLSパラメータ(サーバー側の言語ハンドル)が使用されないことです。この動作を変更するには、SQL*Loaderの制御ファイルに書式マスクを指定するか(初期化パラメータ・ファイルでのNLSパラメータの設定と同じ)、または適切な環境変数を設定できます。たとえば、フィールドに日付書式を指定するには、「SQL*Loaderの制御ファイルの日付書式の設定」に示されているように、SQL*Loaderの制御ファイルに日付書式を設定するか、または「NLS_DATE_FORMAT環境変数の設定」に示されているようにNLS_DATE_FORMAT環境変数を設定できます。

例12-1 SQL*Loaderの制御ファイルに対する日付書式の設定

LOAD DATA
INFILE 'data.dat'
INSERT INTO TABLE emp
FIELDS TERMINATED BY "|"
(
EMPNO NUMBER(4) NOT NULL,
ENAME CHAR(10),
JOB CHAR(9),
MGR NUMBER(4),
HIREDATE DATE 'YYYYMMDD',
SAL NUMBER(7,2),
COMM NUMBER(7,2),
DEPTNO NUMBER(2)
)

例12-2 NLS_DATE_FORMAT環境変数の設定

UnixのBourneまたはKornシェルの場合:

% NLS_DATE_FORMAT='YYYYMMDD'
% export NLS_DATE_FORMAT

UnixのCシェル(csh):

%setenv NLS_DATE_FORMAT='YYYYMMDD'

12.5 SQL*Loaderでの表データの自動パラレル・ロード

Oracle Database 23c以降では、SQL*Loaderのダイレクト・パス・ロードまたは従来型パラレル・ロードでデータ・ファイルを複数の小さいファイルに分割する必要がなくなりました。SQL*Loaderクライアントで自動的にパラレル・ロードを実行できます。

複数の大きい表にあるデータをパラレルでロードすると、時間と労力を節約できます。ソース・データベースとターゲット・データベースからの距離、およびパラレル・スレッドで利用できるシステム・リソースによっては、パラレル・ロードにより、複数の表のロードにかかる時間を大幅に短縮できます。

Oracle Database 23cより前のリリースでは、SQL*Loader (sqlldr)で複数の大きい表のパラレル・ロードを有効にしてロード時間を短縮するには、大きい表を複数の別々の部分に分割した後、ロードする表のセクションごとに、毎回PARALLEL=TRUEコマンド・オプションを指定して複数回SQL*Loaderを実行する必要がありました。

自動パラレル・ロードにより、このプロセスが簡略化されます。パラレル・ロード用に表を手動で準備し、PARALLELパラメータを設定するかわりに、DEGREE_OF_PARALLELISMパラメータを使用して並列度を設定し、1つのコマンドのみでSQL*Loaderを実行することで、同じタスクを自動的に実行できます。DEGREE_OF_PARALLELISMパラメータにより、sqlldrクライアント・ローダー・スレッドの数を設定します。

また、Oracle Database 23c向けSQL*Loader Instant Clientを使用して、Oracle Databaseの以前のリリースに対して同じ自動パラレル・ロードを実行できます。これにより、同じOracle Database 23c機能がSQL*Loaderクライアントを介して以前のリリースのデータベースで使用できるようになります。自動パラレル・ロードは、単一表の場合のみサポートされています。複数のINTO句はサポートされていません。

SQL*Loaderでの表のパラレル・ロードを有効にするには、SQL*LoaderのパラメータDEGREE_OF_PARALLELISMに数値を指定してスレッドの並列度を設定します。csvファイルなど、複数のグラニュルへのデータ分割に対応しているデータ・ファイル形式の場合、パラレルでの読取りとロードではファイルが分割されます。大きいファイルを複数のグラニュルに分割できず、1つのリーダーで読み取る必要がある場合、パラレル・ロードでは、そのリーダーによって複数のローダーにレコードが割り当てられます。たとえば、複雑な文字セットがあるTBサイズのファイルを複数のグラニュルに分割できない場合に、そのファイルを1つのリーダーで読み取るとします。ただし、そのリーダーによって複数のローダーにレコードが割り当てられ、それにより、そのファイルがパラレルでロードされます。複雑な文字セットを含むファイルを複数の入力ファイルに手動で分割する場合、それらを並列処理できます。各ファイルは1つのグラニュルとして扱われます。

SQL*Loaderでシャード表をロードする場合は、複数のスレッドを使用して入力データ・ファイルが読み込まれ、適切なシャード上の表に各レコードがロードされます。

シャード表をパラレルでロードする場合は、SQL*Loaderクライアントによって、入力レコードごとに、ロードする正しいシャードが自動的に判別され、適切なターゲット・ローダー・スレッドに各レコードが割り当てられます。シャードのロードには、従来型パスとダイレクト・パスのどちらでも使用できます。また、表に索引がない場合は、既存のPARALLELオプションを指定してダイレクト・パスを使用することで、各シャード表をロードできます。シャード表の場合は、SQL*LoaderによってDEGREE_OF_PARALLELISMを設定することをお薦めします。ダイレクト・パスは、索引がなくDEGREE_OF_PARALLELISMがシャード数より大きい場合に使用できます。

例12-3 単一表の自動パラレル・ロード

30 GBのt.datというデータ・ファイルがあり、並列処理を有効にしてダイレクト・パス・ロードを使用することで、より迅速にそれをロードする必要があるとします。

次のコマンドでは、ユーザーscottが、DIRECT=TRUEパラメータ・オプションを使用してSQL*Loaderを起動しており、DEGREE_OF_PARALLELISM=5を指定してパラレル・スレッドの数を5に設定しています。

 sqlldr scott/tiger t.ctl direct=true degree_of_parallelism=5

このコマンドでは、5つのリーダー/ローダー・スレッドが起動され、表の入力ファイルが、パラレルでの読取りとロードのために5つのグラニュルに分割されます。

例12-4 シャード表の自動パラレル・ロード

シャード表があり、t.datというデータ・ファイルをロードする必要があるとします。

次に、ローダー・スレッドの数をデフォルトでシャードの数にする例を示します。:

sqlldr scott/tiger t.ctl gsm_name=shdsrv.shpool.oradbcloud gsm_host=example gsm_port=4338

DEGREE_OF_PARALLELISMの値がシャード数より大きい場合、各シャードは複数のローダー・スレッドを使用してロードされます。PARALLEL=FALSEの場合、使用されるローダー・スレッドの数は、切り捨てられてシャードの数になります。

シャード数が100だとすると、次のコマンドでは、SQL*Loaderにより、すべてのシャードをロードするためにデータ・ファイルに対して4つのパスが使用されます(これは、制御ファイル・オプションの句で3つの必須gsmパラメータが指定されていることが前提)。

 sqlldr scott/tiger t.ctl degree_of_parallelism=25

シャード数が10だとすると、次のコマンドでは、SQL*Loaderにより、各シャードの表に2つのスレッドが使用されます。GSMホスト名(gsm_host)はexample、GSM名はshdsrv.shpool.oradbcloud、GSMポート番号(gsm_port)はexample-port-numberです

sqlldr scott/tiger t.ctl degree_of_parallelism=20 gsm_name=shdsrv.shpool.oradbcloud
gsm_host=example gsm_port=example-port-number

シャードをロードするときの読取りバッファを増やすには、SQL*LoaderのREADSIZEパラメータを使用して、より大きいバッファ値を設定します。

ノート:

シャード表に対してPARALLELTRUEに設定してSQL*Loaderを実行した場合、索引メンテナンスはサポートされません。デフォルトでは、ローカル索引メンテナンスがサポートされます。この場合、シャードごとに1つのスレッドのみが使用されます。

12.6 自動パラレル・ロードの場合のロード・モードおよびオプション

SQL*Loaderを使用した従来型パス・ロードとダイレクト・パス・ロードの両方について、シャード表と非シャード表の自動パラレル・ロードでのロード・モードおよびオプションを説明します。

12.6.1 自動パラレル・ロードの場合のロード・モード

Oracle Database 23c以降では、SQL*Loaderで、データ・ファイルのパラレル・ロード用に3つのモードが使用されます。

自動パラレル・ダイレクト・パス・ロードでは、ネットワーク・トラフィックが複数のパケットに分割されるのと同様に、SQL*Loaderによって自動的にデータ・ファイルが複数のグラニュルに分割されます。可能な場合は、SQL*Loaderにより、パラレル・リーダーおよびローダーを使用してパラレル・ロードのために自動的に入力ファイルが複数の小さいグラニュルに分割されます。SQL*Loaderでは、データの各グラニュルが追跡され、リーダー数とローダー数、および表データに使用可能なロード・オプションに基づいて、ソース・システムからターゲット・システムへのデータの転送が最適化されます。SQL*Loaderのログ・ファイルには、使用されたモード、およびリーダーでのパラレル・ロードの実行方法が記録されます。この機能を使用するために必要なのは、ロードする表の特性に合わせてSQL Loaderのパラメータを設定することのみです。

SQL*LoaderパラメータCREDENTIALを使用して、オブジェクト・ストアへの読取りアクセスを有効にする資格証明を提供できます。オブジェクト・ストアからのパラレル・ロードがサポートされています。

DEGREE_OF_PARALLELISMパラメータにより、sqlldrクライアント・ローダー・スレッドの数を設定します。

SQL*Loaderのデフォルトでは、OPTIMIZE_PARALLEL=TRUEが想定されています。SQL*Loaderでの自動パラレル・ロードは、デフォルトでは、使用可能な最速のモードになります。また、使用可能なモードは、データを非シャード表にロードするかシャード表にロードするかで異なります。

SQL*Loaderで使用される3種類の操作モードを次に示します。

  • モード1: SQL*Loaderクライアントの各スレッドがリーダーとローダーになります。このモードは、シャード表には使用できません。
  • モード2: 1つ以上のSQL*Loaderリーダーによって複数のローダーにレコードが割り当てられます。複数のリーダーがある場合は、各データ・ファイルが複数のグラニュルに分割され、各グラニュルがリーダー・スレッドによって処理されて、適切なローダー・スレッドにそのレコードが割り当てられます。ファイルを複数のグラニュルに分割してパラレルで読み取ることができない場合、ファイルは1つのグラニュルとしてのみ処理されます。各グラニュルからのレコードは、複数のローダー・スレッドによってロードされます。
  • モード3: データ・ファイルは複数のグラニュルに分割されません。そうではなく、すべてのスレッドによって、データすべてが読み取られます。ただし、選択したレコードのみがロードされます。より速い方法のいずれかを使用できない場合、SQL*Loaderはデフォルトでモード3になります。

12.6.2 SQL*Loaderの非シャード自動パラレル・ロード・モード

自動的にデータ・ファイルの最速ロードを実現するためにSQL*Loaderでどのように非シャード表が処理されるかを説明します。

ノート:

自動パラレル・ロードのパフォーマンスは、ファイルを手動で分割し、parallel=trueを指定して複数の同時ダイレクト・パス・ロードを発行する以前の方法と同様になります。

モード1: リーダーとローダー(グラニュルあり)

非シャード表の場合、OPTIMIZE_PARALLELTRUEに設定すると、SQL*Loaderクライアントの各スレッドがリーダーとローダーになります。SQL*Loaderによってデータ・ファイルがデータの複数のグラニュルに分割され、そのスレッドによってこれらのグラニュルが解析されロードされます。非シャード表のパラレル・ロードの場合は、これが最速の方法です。

DEGREE_OF_PARALLELISMにより、リーダー・スレッドとローダー・スレッドの数が決まります。ログ・ファイルには、これらのスレッドがreader/loaderスレッドとして記録されます。READER_COUNTは、このモードでは無視されます。

モード2: リーダーとローダー(グラニュルあり)

非シャード表の場合、OPTIMIZE_PARALLELTRUEに設定したが、モード1を使用できない場合、デフォルトはモード2になります。モード2では、m個のリーダーとn個のローダーがあります。mの値はREADER_COUNTによって決まり、nの値はDEGREE_OF_PARALLELISMの値によって決まります。並列度は、非シャード表の場合のみ指定する必要があります。

DEGREE_OF_PARALLELISMにより、ローダー・スレッドの数が決まります。READER_COUNTにより、リーダーの数が決まります。シャード表をパラレルでロードする場合は、これが最速モードです。

モード2では、リーダー・スレッドとローダー・スレッドはログ・ファイルにおいてreaderスレッドまたはloaderスレッドとして別々に示されます。非シャード表をロードする場合、これは非最適化モードです。

ログ・ファイル内の統計で示されている、ローダーがリーダーを待機する時間が長い場合は、リーダー数を増やすとロード速度が上がる可能性があります。リーダーがローダーを待機する時間が長い場合は、ローダー数を増やすとロード速度が上がる可能性があります。また、READSIZEを大きくすると、モード2のパフォーマンスが向上する可能性があります。

モード3: リーダーとローダーですべてのファイルを読み取る(グラニュルなし)

モード1またはモード2を使用できない場合、SQL*Loaderはデフォルトでモード3になります。このモードでは、reader/loaderスレッドによってすべてのデータ・ファイルが読み取られて分析され、パラレル・ロードの要求に応じてレコードがロードされる必要があります。これは、最も最適化度が低いパラレル処理モードです。このモードは、デリミタ付きLOBをロードする場合に必要になります。SQL*Loaderで、レコードを処理するときにLOBFILES内のその位置を追跡する必要があるためです。

例12-5 モード2の非シャード・パラレル・ロードのログ・ファイル

SQL*Loader: Release 23.0.0.0.0 - Development on Thu Sep 22 11:54:31 2022 Version 23.1.0.0.0

Copyright (c) 1982, 2022, Oracle and/or its affiliates.  All rights reserved.

Control File:   fact_page.ctl
Data File:      /scratch/fact_page.dat
   Bad File:     fact_page.bad
   Discard File:  none specified

  (Allow all discards)

Number to load: ALL
Number to skip: 0
Errors allowed: 50
Continuation:    none specified
Path used:      Direct - with parallel option.

Load is UNRECOVERABLE; invalidation redo is produced.

Table L_FACT_PAGE, loaded from every logical record.
Insert option in effect for this table: APPEND TRAILING NULLCOLS option in effect

Column Name           Position    Len    Term   Encl    Datatype
--------------------  ----------  -----  ----   ----  ---------------------
PAGE_ID               FIRST       50     |            CHARACTER 
SESSION_ID            NEXT        50     |            CHARACTER 
IP_ID                 NEXT        50     |            CHARACTER 
DATE_ID               NEXT        *      |            DATE YYYY-MM-DD 
SECOND_ID             NEXT        50     |            CHARACTER 
LOCATION_ID           NEXT        50     |            CHARACTER 
SERVER_ID             NEXT        50     |            CHARACTER 
REF_PAGE_ID           NEXT        50     |            CHARACTER 
RET_CODE_ID           NEXT        50     |            CHARACTER 
PAGE_KEY_ID           NEXT        50     |            CHARACTER 
PAGE_NAME             NEXT        50     |            CHARACTER 
REFER_PAGE_NAME       NEXT        50     |            CHARACTER 
REFER_URL             NEXT        250    |            CHARACTER
COUNT_1               NEXT        50     |            CHARACTER 
NUM_BYTES             NEXT        50     |            CHARACTER 
ENTRY_EXIT_FLAG       NEXT        50     |            CHARACTER 
MEMBER_FLAG           NEXT        50     |            CHARACTER 
QUERY_ID              NEXT        100    |            CHARACTER


   3 Total granules for all files to be loaded.


Table L_FACT_PAGE:
Reader/Loader: Thread 1
Granules/Files Assigned: 1
Rows Assigned: 3353354
Elapsed time reading input data:                      00:00:00.14
Elapsed time loading stream data:                     00:00:03.32
Average stream buffer size:                           497121
Total number of stream buffers loaded:                675

   3353354 Rows successfully loaded.
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

   Date cache:
    Max Size:      1000
    Entries :         1
    Hits    :   3353353
    Misses  :         0

CPU time was:         00:00:10.03

Elapsed time loading stream data for this thread:     00:00:03.32

12.6.3 SQL*Loaderのシャード自動パラレル・ロード・モード

シャード表のSQL*Loader自動パラレル・ロードは、ここで説明するモードを使用して自動的に実行されます。

ノート:

モード1は、シャード表には使用できません。

シャードをロードする場合は、Oracle Global Service Managerの3つのシャード・ディレクタ(gsm)パラメータ(gsm_namegsm_hostおよびgsm_port)をすべて指定する必要があります。DEGREE_OF_PARALLELISMパラメータは、自動的に、ロードするシャードの数に設定されます。デフォルトでは、すべてのシャードがロードされます。SQL*Loaderでは、個々のシャードでロードに関する問題が検出された場合でも、他のシャードのロードは続行されます。後でログ・ファイルを調べて、どのシャードが正常にロードされ、どのシャードが失敗したかを確認し、問題を解決できます。その後、LOAD_SHARDSパラメータを使用して、ロードに失敗したシャードをロードできます。SQL*Loaderでは、LOAD_SHARDSでリストしないシャードは無視されます。COMPRESS_STREAM=TRUEを設定すると、シャードのロードを高速化できます。シャード表の場合は、SQL*LoaderによってDEGREE_OF_PARALLELISMを設定することをお薦めします。ダイレクト・パスは、索引がなくDEGREE_OF_PARALLELISMがシャード数より大きい場合に使用できます。

モード2: シャード表のリーダーとローダー(グラニュルあり)

OPTIMIZE_PARALLELTRUEに設定した場合は、モード2が使用されます。シャード表をパラレルでロードする場合は、これが最速モードです。

DEGREE_OF_PARALLELISMにより、ローダー・スレッドの数が決まります。このオプションは、ロードするシャードの数に自動的に設定されます。デフォルトはall shardsです。READER_COUNTにより、リーダーの数が決まります。リーダー・スレッドとローダー・スレッドは、ログ・ファイルにおいてreaderスレッドまたはloaderスレッドとして別々に示されます。シャードをロードする場合は、gsm_namegsm_hostおよびgsm_portを指定する必要があります。DEGREE_OF_PARALLELISMをシャード数より小さい値に設定すると、SQL*Loaderによって、すべてのシャードがロードされるまで入力データに対して複数のパスが実行されます。このオプションは、SQL*Loaderクライアント・システムで多数のスレッドを効率的に処理できない場合に選択できます。

ログ・ファイル内の統計で示されている、ローダーがリーダーを待機する時間が長い場合は、READER_COUNTの値を大きくするとロード・パフォーマンスが向上する可能性があります。リーダーがローダーを待機する時間が長い場合は、ローダー数を増やすとロード・パフォーマンスが上がる可能性があります。また、READSIZEを大きくすると、モード2のパフォーマンスが向上する可能性があります。

モード3: シャード表の場合はリーダーとローダーですべてのファイルを読み取る(グラニュルなし)

モード2を使用できない場合、SQL*Loaderはデフォルトでモード3になります。モード3では、すべてのreader/loaderスレッドによって、すべてのデータ・ファイルが読み取られて処理され、パラレル・ロードの要求に応じてレコードがロードされる必要があります。これは、最も最適化度が低いパラレル処理モードです。このモードは、デリミタ付きLOBをロードする場合に必要です。

例12-6 モード2のシャード・パラレル・ロードのログ・ファイル

SQL*Loader: Release 23.0.0.0.0 - Development on Thu Jan 12 16:53:28 2023 Version 23.1.0.0.0

Copyright (c) 1982, 2023, Oracle and/or its affiliates.  All rights reserved.

Control File:   fact_page_shard.ctl
Data File:      /scratch/rphillip/fact_page.dat
   Bad File:     fact_page.bad
   Discard File:  none specified

  (Allow all discards)

Number to load: 1234
Number to skip: 0
Errors allowed: 50
Continuation:    none specified
Path used:      Direct

Table L_FACT_PAGE, loaded from every logical record.
Insert option in effect for this table: TRUNCATE TRAILING NULLCOLS option in effect

Column Name           Position    Len    Term   Encl    Datatype
--------------------  ----------  -----  ----   ----  ---------------------
PAGE_ID               FIRST       50     |            CHARACTER 
SESSION_ID            NEXT        50     |            CHARACTER 
IP_ID                 NEXT        50     |            CHARACTER 
DATE_ID               NEXT        *      |            DATE YYYY-MM-DD 
SECOND_ID             NEXT        50     |            CHARACTER 
LOCATION_ID           NEXT        50     |            CHARACTER 
SERVER_ID             NEXT        50     |            CHARACTER 
REF_PAGE_ID           NEXT        50     |            CHARACTER 
RET_CODE_ID           NEXT        50     |            CHARACTER 
PAGE_KEY_ID           NEXT        50     |            CHARACTER 
PAGE_NAME             NEXT        50     |            CHARACTER 
REFER_PAGE_NAME       NEXT        50     |            CHARACTER 
REFER_URL             NEXT        250    |            CHARACTER
COUNT_1               NEXT        50     |            CHARACTER 
NUM_BYTES             NEXT        50     |            CHARACTER 
ENTRY_EXIT_FLAG       NEXT        50     |            CHARACTER 
MEMBER_FLAG           NEXT        50     |            CHARACTER 
QUERY_ID              NEXT        100    |            CHARACTER

   4 Total granules for all files to be loaded.


Loading the following shards (all):
shpool%1
shpool%11
shpool%21
shpool%31
shpool%41


Table L_FACT_PAGE:
Reader: Thread 2
Granules/Files Assigned: 1
Rows Assigned: 231
Elapsed time reading input data:                      00:00:00.04

   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

CPU time was:         00:00:00.03


Table L_FACT_PAGE:
Reader: Thread 1
Granules/Files Assigned: 1
Rows Assigned: 825
Elapsed time reading input data:                      00:00:00.04

   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

CPU time was:         00:00:00.05


Table L_FACT_PAGE:
Reader: Thread 4
Granules/Files Assigned: 1
Rows Assigned: 0
Elapsed time reading input data:                      00:00:00.01

   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

CPU time was:         00:00:00.03


Table L_FACT_PAGE:
Reader: Thread 3
Granules/Files Assigned: 1
Rows Assigned: 178
Elapsed time reading input data:                      00:00:00.02

   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

CPU time was:         00:00:00.03


Table L_FACT_PAGE:
Load Thread For Shard: shpool%41
   206 Rows successfully loaded.
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

   Date cache:
    Max Size:      1000
    Entries :         1
    Hits    :       205
    Misses  :         0

   Partition L_FACT_PAGE_P11: 104 Rows loaded.
   Partition L_FACT_PAGE_P12: 102 Rows loaded.

CPU time was:         00:00:00.02

Elapsed time loading stream data for this thread:     00:00:00.01
Average stream buffer size:                           19969
Total number of stream buffers loaded:                1


Table L_FACT_PAGE:
Load Thread For Shard: shpool%21
   198 Rows successfully loaded.
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

   Date cache:
    Max Size:      1000
    Entries :         1
    Hits    :       197
    Misses  :         0

   Partition L_FACT_PAGE_P7: 91 Rows loaded.
   Partition L_FACT_PAGE_P8: 107 Rows loaded.

CPU time was:         00:00:00.02

Elapsed time loading stream data for this thread:     00:00:00.01
Average stream buffer size:                           19077
Total number of stream buffers loaded:                1


Table L_FACT_PAGE:
Load Thread For Shard: shpool%1
   284 Rows successfully loaded.
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

   Date cache:
    Max Size:      1000
    Entries :         1
    Hits    :       283
    Misses  :         0

   Partition L_FACT_PAGE_P1: 87 Rows loaded.
   Partition L_FACT_PAGE_P2: 104 Rows loaded.
   Partition L_FACT_PAGE_P3: 93 Rows loaded.

CPU time was:         00:00:00.02

Elapsed time loading stream data for this thread:     00:00:00.01
Average stream buffer size:                           27499
Total number of stream buffers loaded:                1


Table L_FACT_PAGE:
Load Thread For Shard: shpool%31
   203 Rows successfully loaded.
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

   Date cache:
    Max Size:      1000
    Entries :         1
    Hits    :       202
    Misses  :         0

   Partition L_FACT_PAGE_P10: 109 Rows loaded.
   Partition L_FACT_PAGE_P9: 94 Rows loaded.

CPU time was:         00:00:00.02

Elapsed time loading stream data for this thread:     00:00:00.00
Average stream buffer size:                           19714
Total number of stream buffers loaded:                1


Table L_FACT_PAGE:
Load Thread For Shard: shpool%11
   343 Rows successfully loaded.
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

   Date cache:
    Max Size:      1000
    Entries :         1
    Hits    :       342
    Misses  :         0

   Partition L_FACT_PAGE_P4: 102 Rows loaded.
   Partition L_FACT_PAGE_P5: 127 Rows loaded.
   Partition L_FACT_PAGE_P6: 114 Rows loaded.

CPU time was:         00:00:00.02

Elapsed time loading stream data for this thread:     00:00:00.00
Average stream buffer size:                           33089
Total number of stream buffers loaded:                1


Table L_FACT_PAGE:
Main Thread
Total Granules/Files Assigned: 4
   0 Rows not loaded due to data errors.
   0 Rows not loaded because all WHEN clauses were failed.
   0 Rows not loaded because all fields were null.

1234 Total rows for all shards successfully loaded.

Bind array size not used in direct path.
Column array  rows :    5000
Stream buffer bytes:  512000
Read   buffer bytes:41943040

Total logical records skipped:          0
Total logical records read:          1234
Total logical records rejected:         0
Total logical records discarded:        0
Direct path multithreading optimization is disabled

Run began on Thu Jan 12 16:53:28 2023
Run ended on Thu Jan 12 16:53:38 2023

Elapsed time was:     00:00:09.76
CPU time was:         00:00:00.30

Elapsed time for loader threads waiting for records:  00:00:00.30
Elapsed time for reader threads waiting for loaders:  00:00:00.30
Elapsed time reading input data:                      00:00:00.11
Elapsed time loading stream data:                     00:00:00.03
Average stream buffer size:                           23869
Total number of stream buffers loaded:                5




The following shards were successfully loaded:
Load successful for shard: shpool%1
Load successful for shard: shpool%11
Load successful for shard: shpool%21
Load successful for shard: shpool%31
Load successful for shard: shpool%41

12.7 ダイレクト・パス・ロードの使用

SQL*Loaderのダイレクト・パス・ロード方法を使用してデータをロードする方法を学習します。

12.7.1 ダイレクト・パス・ロードのセットアップ

ダイレクト・パス・ロード用にデータベースを準備するために必要なビューを作成するには、セットアップ・スクリプトcatldr.sqlを実行する必要があります。

catldr.sqlを実行する必要があるのは、ダイレクト・ロードを実行する予定の各データベースに対して1回のみです。データベースのインストール時に、ダイレクト・ロードを実行することがわかっている場合は、データベースのインストール中にこのスクリプトを実行することもできます。

12.7.2 ダイレクト・パス・ロードの指定

SQL*Loaderをダイレクト・パス・ロード・モードで起動するには、コマンドラインまたはパラメータ・ファイルのDIRECTパラメータをTRUEに設定します。

たとえば、ダイレクト・パス・ロード・モードでSQL*Loaderを起動するようにパラメータ・ファイルを構成するには、パラメータ・ファイルに次の行を含めます。

DIRECT=TRUE

12.7.3 索引の作成

一時記憶域を使用すると、ダイレクト・パス・ロードのパフォーマンスが向上します。各ブロックがフォーマットされた後、新しい索引キーがソート(一時)セグメントに挿入されます。

ロードが終了すると、古い索引と新しいキーがマージされ、新しい索引が作成されます。古い索引、ソート(一時)セグメント、新しい索引セグメントでは、すべてのマージが完了するまで記憶域が必要です。最後に、古い索引と一時セグメントが削除されます。

従来型パス・ロードでは、行が挿入されるたびに索引が更新されます。この方法では一時記憶域は不要ですが、処理に時間がかかります。

12.7.3.1 パフォーマンスの向上

メモリーに制限があるシステムでSQL*Loaderダイレクト・ロードのパフォーマンスを向上するには、SINGLEROWパラメータを使用します。

ノート:

ダイレクト・ロード時にデータの事前ソートを指定してあり、既存の索引が空である場合、一時セグメントは不要でマージもされません。この場合は、索引にキーが直接付加されます。

ダイレクト・パス・ロードのパフォーマンスの最適化を参照してください

複数の索引が作成されると、古い索引の他に、各索引に対応する一時セグメントが同時に存在するようになります。次に、新しいキーは一度に1索引ずつ古い索引とマージされます。新しい各索引が作成されると、古い索引とそれに対応する一時セグメントは削除されます。

12.7.3.2 一時セグメント記憶域要件の計算

新規索引キーを格納するためにダイレクト・パス・ロード中に必要な一時セグメント領域の量を見積もるには、次の式を使用します。

新しい索引キーの格納に必要な一時セグメント領域の大きさ(バイト単位)を計算するには、次の式を使用します。

1.3 * key_storage

この式では、キー・ストレージは次のように定義されます。number_rowsは行数、sum_of_column_sizesは列サイズの合計、number_of_columnsは索引内の列数です。

key_storage = (number_rows) *  
( 10 + sum_of_column_sizes + number_of_columns )

この式における列(column)とは、索引の列を意味します。ここでは、1列につき1バイトを使用しています。さらに、ROWID,やその他のオーバーヘッドとして1行につき10バイトを計算に入れています。

定数1.3は、ソートに必要な追加領域の平均的な大きさを反映しています。この値は、データの順序がきわめてランダムな場合に有効です。データが逆の順序に並んでいると、ソートには2倍のキー記憶域が必要となるため、そのときは定数値を2.0とします。ただし、これは最悪の場合です。

データが完全にソートされている場合は、索引エントリを格納できる領域のみが必要なため、そのときの定数の値は1.0に下がります。

12.7.4 使用禁止状態(Index Unusable)のままの索引

ロードされているデータ・セグメントが、その索引の索引セグメントより新しいものになると、SQL*Loaderによって索引が索引使用禁止状態になります。

SQL文が索引使用禁止状態の索引を参照しようとすると、エラーが発生します。ダイレクト・パス・ロードの実行時に、次のような状況が発生すると、索引またはパーティション索引のパーティションは索引使用禁止状態になります。

  • SQL*Loaderで索引のための領域が少なくなり、索引が更新できない場合。

  • データがSORTED INDEXES句で指定した順序になっていない場合。

  • インスタンス障害が発生したか、または索引作成中にOracleシャドウ・プロセスが失敗した場合。

  • 一意の索引内に重複キーがある場合。

  • データ・セーブポイントを使用中、データ・セーブポイント発生後にロードが正常に実行されないか、またはキーボードからの中断によって終了された場合。

ある索引が索引使用禁止状態かどうかを調べるには、次に示す簡単な問合せを実行します。

SELECT INDEX_NAME, STATUS
   FROM USER_INDEXES 
   WHERE TABLE_NAME = 'tablename';

表の所有者でない場合は、USER_INDEXESのかわりに、ALL_INDEXESまたはDBA_INDEXESを検索してください。

ある索引パーティションが使用禁止状態かどうかを調べるには、次に示す問合せを実行します。

SELECT INDEX_NAME, 
       PARTITION_NAME,
       STATUS FROM USER_IND_PARTITIONS
       WHERE STATUS != 'VALID';

表の所有者でない場合は、USER_IND_PARTITIONSのかわりに、ALL_IND_PARTITIONSおよびDBA_IND_PARTITIONSを検索します。

12.7.5 データ・セーブによるデータ損失の防止

データ・セーブを使用して、インスタンス障害によるデータ損失を回避できます。

12.7.5.1 データ・セーブを使用したデータ損失の防止

セーブポイントがある場合、SQL*Loaderのロード中にインスタンス障害が発生した場合は、SKIPパラメータを使用してロードを続行します。

最後のセーブポイントにロードされたすべてのデータが、インスタンス障害から保護されます。

インスタンス障害後にロードを続行する場合は、障害発生前に入力ファイルから何行処理されたか判別し、SKIPパラメータを使用して、処理済の行をスキップします。

表に索引がある場合には、ロードを続行する前にそれらの索引を削除し、ロード後に索引を再作成してください。メディア障害およびインスタンス・リカバリの詳細は、「ダイレクト・パス・ロード時のデータ・リカバリ」を参照してください。

ノート:

SQL*Loaderではデータのロードが完了するまで索引が作成されないため、索引はデータ・セーブでは保護されません(事前ソートされたデータを空の表にロードする場合にかぎり、ロード中に索引が作成されますが、その場合も索引は保護されません。)

12.7.5.2 ROWSパラメータの使用

ROWSパラメータには、ダイレクト・パス・ロードでデータ・セーブを行う間隔を設定します。

ROWSに指定する値は、データベースへの挿入を保存する前に、SQL*Loaderによって入力ファイルから読み込まれる行数です。

データ・セーブは負荷の高い操作です。データ・セーブの間隔が15分以上になるように、ROWSを十分高い値に設定してください。これによって、長時間のダイレクト・パス・ロードの実行中にインスタンス障害が発生したときに、損失する作業量の上限(最高水位標)を指定できます。ROWSに小さい値を設定すると、パフォーマンスおよびデータ・ブロック領域使用率が低下します。

12.7.5.3 データ・セーブとコミット

従来型ロードでは、ROWSはコミット操作の前に読み込む行数を意味します。ダイレクト・ロードにおけるデータ・セーブは、従来型ロードにおけるコミットと同様ですが、異なる部分もあります。

類似点は次のとおりです。

  • データ・セーブを行うと他のユーザーもその行を参照できます。

  • データ・セーブ後は、行をロールバックできません。

一方、従来型との主な相違点は、ダイレクト・パス・ロードのデータ・セーブではロードが完了するまで索引が使用できない(索引使用禁止状態)ということです。

12.7.6 ダイレクト・パス・ロード時のデータ・リカバリ

ダイレクト・パス・ロード方法を指定すると、SQL*Loaderのデータ・リカバリ機能が完全にサポートされます。

リカバリには大きく分けて2種類あります。

  • メディア・リカバリは、損失したデータベース・ファイルをリカバリします。データベース・ファイルを損失した場合に、それをリカバリできるようにするには、ARCHIVELOGモードで実行する必要があります。

  • インスタンス・リカバリは、障害が発生する前にインメモリー・データが変更されたが、ディスクに書き込まれる前に障害のため失われてしまったというシステム障害をリカバリします。Oracle Databaseでは、REDOログ・ファイルがアーカイブされていない場合も、インスタンス障害をリカバリできます。

12.7.6.1 メディア・リカバリおよびダイレクト・パス・ロード

REDOログ・ファイル・アーカイブ機能が使用可能になっている( ARCHIVELOGモードで実行している)場合、ダイレクト・パスでロードしたデータは、SQL*Loaderによってログに記録されます。それによって、メディア・リカバリが可能になります。

REDOログ・ファイル・アーカイブの機能が使用可能になっていない(NOARCHIVELOGモードで実行している)場合、メディア・リカバリはできません。

ロード中に失われたデータベース・ファイルをリカバリするには、従来型パスでロードしたデータをリカバリするときと同じ方法を使用してください。

  1. 影響を受けたデータベース・ファイルの最新のバックアップをリストアします。
  2. RMAN RECOVERコマンドを使用して、表領域をリカバリします。
12.7.6.2 インスタンス・リカバリおよびダイレクト・パス・ロード

データベース・ファイルは、SQL*Loaderによって直接書き込まれます。そのため、インスタンスを再起動すると、最後にデータをセーブした時点までに挿入したすべての行が、自動的にデータベース・ファイルに存在します。

変更がREDOログ・ファイルに記録されていなくても、インスタンス・リカバリは可能です。

インスタンス障害が発生すると、作成中の索引は索引使用禁止状態のままになります。使用禁止状態の索引は、表またはパーティションを使用する前に再構築する必要があります。索引が索引使用禁止状態のままであるかどうかを調べる方法については、「使用禁止状態(Index Unusable)のままの索引」を参照してください。

12.7.7 LONG型データ・フィールドのロード

ラージ・オブジェクト・タイプ(LOB)を使用することにより、SQL*Loaderの最大バッファ・サイズがダイレクト・パスにロードできるよりも長いデータをロードできます。

長いデータ・フィールドのロード方法を検討する際には、次の点に注意してください。

  • 長いデータ・フィールドをLOBとしてロードするパフォーマンスを向上させるために、大きなSTREAMSIZE値を使用することをお薦めします。
  • LOBのかわりに、PIECEDパラメータを使用して、最大バッファ・サイズよりも長いデータを読み込むこともできます。ただし、このシナリオでは、PIECEDのかわりにLOBを使用することをお薦めします。

12.7.8 PIECEDとしてのデータのロード

データが論理レコードの最終列である場合、PIECEDパラメータを使用すると、データをセクションごとにロードできます。

列をPIECEDと宣言することによって、LONGフィールドを複数の物理レコード(ピース)に分割することが、ダイレクト・パス・ローダーに通知されます。この場合、SQL*Loaderでは、LONGフィールドの各ピースが物理レコード内で検索された順序で処理されます。レコードが処理される前に、フィールドのすべてのピースが読み込まれます。SQL*Loaderでは、格納前のLONGフィールドは具体化されません。ただし、レコードが処理される前に、フィールドのすべての部分が読み込まれます。

列をPIECEDと宣言する場合、次の制約が適用されます。

  • このオプションはダイレクト・パスでのみ有効です。

  • 1つの表につき1フィールドのみをPIECEDにできます。

  • PIECEDフィールドは論理レコードの最終フィールドである必要があります。

  • WHEN句、NULLIF句またはDEFAULTIF句では、PIECEDフィールドを使用できません。

  • 論理レコード内のPIECEDフィールドの領域は、他のフィールドの領域と重複してはいけません。

  • PIECEDに対応するデータベースの列を索引に含めることはできません。

  • 拒否されたレコードにPIECEDフィールドが含まれている場合は、不良ファイルからそのレコードをロードできません。

    たとえば、1つのPIECEDフィールドが3つのレコードにまたがっているとします。SQL*Loaderでは、最初のレコードからPIECEDフィールドの第一分割がロードされ、次に同じバッファを使用して2番目のレコードから第二分割がロードされます。その後、同じバッファを使用して同様に3番目のレコードがロードされます。ここでエラーが検出されると、最初の2つのレコードはすでにバッファには存在しないため、3番目のレコードのみが不良ファイルに書き込まれます。その結果、不良ファイルにあるレコードが無効となります。

12.7.9 ダイレクト・パス・モードを使用するSQL*Loader操作の監査

選択したユーザー・データベース・アクションを監視および記録するため、SQL*Loaderのダイレクト・パス・ロードの監査を実行できます。

SQL*Loaderでは、すべての監査レコードが1つの場所に一元化される統合監査を使用します。

統合監査を設定するには、統合監査ポリシーを作成するか、既存のポリシーを変更します。監査ポリシーは、データベースにおけるユーザー動作の特定の部分を監査できる監査設定の名前付きグループです。ポリシーを作成するには、SQL CREATE AUDIT POLICY文を使用します。

監査ポリシーを作成したら、AUDITおよびNOAUDIT SQL文を使用してポリシーをそれぞれ有効化および無効化します。

12.8 手動ダイレクト・パス・ロードのパフォーマンスの最適化

ダイレクト・パス・ロードを手動で構成することにした場合の、SQL*Loaderダイレクト・パス・ロードをより高速に実行する方法、および使用領域を減らす方法について説明します。

12.8.1 ダイレクト・パス・ロードに必要な時間と領域の最小化

ダイレクト・パス・ロードでは、使用する時間と一時記憶域を制御できます。

時間を最小化するには:

  • 記憶域の事前割当て
  • データの事前ソート
  • データ・セーブの回数の削減
  • REDOログの最小限の使用
  • 配列行の列数およびストリーム・バッファのサイズを指定

  • 日付キャッシュの値の指定
  • DB_UNRECOVERABLE_SCN_TRACKING=FALSEと設定します。リカバリ不能な(nologging)ダイレクト書込みは、SCNと最終ダイレクト書込みの時間を定期的に格納することによって、制御ファイル内で追跡されます。制御ファイルへのこれらの更新がパフォーマンスに悪影響を及ぼす場合は、DB_UNRECOVERABLE_SCN_TRACKINGパラメータをFALSEに設定すると、パフォーマンスが向上することがあります。

領域を最小化するには:

  • ロード前のデータのソート時に、最も多くの一時記憶域を必要とする索引でデータをソートします。
  • ロード中の索引メンテナンスを回避します。

12.8.2 高速ロードのための記憶域の事前割当て

SQL*Loaderでは、必要に応じて自動的に表にエクステントが追加されますが、これには時間がかかります。新しい表へ高速にロードするには、表の作成に必要なエクステントを事前に割り当ててください。

表に必要な領域を計算するには、Oracle Database管理者ガイドのデータベース・ファイルの管理の説明を参照してください。必要な領域を割り当てるには、SQLのCREATE TABLE文でINITIALまたはMINEXTENTS句を使用します。

別の方法として、エクステントの割当て回数が減るようにエクステントのサイズを十分に大きくする方法もあります。

12.8.3 高速索引付けのためのデータの事前ソート

索引付き列を基準にしてデータを事前ソートすると、SQL*Loaderのダイレクト・パス・ロードのパフォーマンスを改善できます。

12.8.3.1 データの事前ソートの利点

事前ソートによって、SQL*Loaderでのロード・パフォーマンスを向上させる方法について学習します

事前ソートを行うと、ロード時の一時記憶要件を最小限に抑えることができます。また、事前ソートでは、ご使用のオペレーティング・システムまたはアプリケーション用に最適化された高性能ソート・ルーチンを利用できます。

データが事前ソートされていて既存の索引が空でない場合は、事前ソートによって、新しいキーに必要な一時セグメント領域の大きさを最小にできます。ソート・ルーチンは、新しい各キーをキー・リストに追加します。ソート用の追加領域は必要なく、キーのための領域のみが必要となります。必要な記憶域の大きさを計算するには、ソート係数として1.3ではなく1.0を使用してください。必要な記憶域要件の見積りについては、「一時セグメント記憶域要件」を参照してください。

事前ソートを指定していて既存の索引が空である場合は、最大効率が実現します。新しいキーが索引に挿入されるのみです。一時セグメントと新しい索引が古い空の索引と同時に存在するのではなく、新しい索引のみが存在します。その結果、ロード中に一時的な記憶域が不要になり、時間が節約されます。

12.8.3.2 SORTED INDEXES句

SORTED INDEXESは、データを事前ソートしている索引を指定します。

この句は、ダイレクト・パス・ロードでのみ使用できます。例については、「事例6: ダイレクト・パス・ロード方式を使用したデータのロード」を参照してください。(事例の使用方法については、「SQL*Loaderの事例」を参照してください。)

一般に、SORTED INDEXES句では1つの索引のみを指定します。通常、これは、ある索引でソートされたデータは、別の索引にとって正しい順序とはかぎらないためです。ただし、複数の索引のデータの順序が同じである場合は、索引すべてを同時に指定できます。

SORTED INDEXES句で指定した索引はすべて、ダイレクト・パス・ロードを開始する前に作成する必要があります。

12.8.3.3 未ソートのデータ

SORTED INDEXES句で索引を指定しても、データがその索引でソートされていない場合は、ロード終了時に索引は索引使用禁止状態のままになります。

データは存在していますが、索引を使用しようとするとエラーになります。索引使用禁止状態の索引がある場合は、ロード後に再構築してください。

12.8.3.4 複数列索引

SORTED INDEXES句で複数列の索引を指定する場合は、まず索引の最初の列で順序付けが行われ、次に2番目の列で順序付けが行われるように、データをソートしてください。

たとえば、索引の最初の列に都市名があり、2番目の列に名前の名字がある場合、次のリストのように都市別順で、同じ都市の中では名字順に並ぶようにデータをソートします。

Albuquerque      Adams
Albuquerque      Hartstein
Albuquerque      Klein
...         ...
Boston           Andrews
Boston           Bobrowski
Boston           Heigham
...              ...
12.8.3.5 最適ソート順序の選択方法

ダイレクト・パス・ロードのパフォーマンスを最大限に引き出すには、最も大きな一時セグメント領域を必要とする索引に基づいて、データを事前ソートしてください。

たとえば、主キーが1つの数値列で、2次キーが3つのテキスト列で構成される場合、2次キーで事前ソートすることによって、ソート時間と記憶要件の両方を最小にできます。

最も大きな記憶域を必要とする索引がどれであるかを知るには、次の手順に従ってください。

  1. 各索引について、その索引のすべての列の幅を加算します。
  2. 単一表へのロードの場合は、最大幅を持つ索引を選択します。
  3. 複数表へのロードの場合は、各表に対して最大幅を持つ索引を調べます。各表にロードされる行数が同じ場合は、最大幅を持つ索引を選択します。通常は、各表にロードされる行数は同じです。
  4. 複数表へのロードにおいて、索引付きの表にロードされる行数が表によって異なる場合は、ステップ3で確認した各索引の幅と、その索引にロードされる行数を掛け合せます。結果が最も大きい値の索引を選択します。

12.8.4 データ・セーブの回数の削減

ROWS値が小さいことが原因でデータ・セーブが頻繁に発生する場合、ダイレクト・パス・ロードのパフォーマンスは低下します。

ROWS値が小さい場合、セーブ後に最後のデータ・ブロックには書込みが行われないため、データ・ブロック領域が無駄になります。

ダイレクト・パス・ロードは従来型ロードより何倍も高速なため、ダイレクト・ロードの場合には、ROWSの値は従来型ロードの場合よりかなり大きくする必要があります。

データ・セーブ時には、SQL*Loaderのすべてのバッファへの書込みが正常に終了するまで、ロードは停止します。ROWSの値は、安全性を確保できる範囲で、できるだけ大きくしてください。数千行をロードしてみて、1行当たりの平均ロード時間を計ってみることをお薦めします。その値から、ROWSに設定する値が求められます。

たとえば、1分当たり20,000行がロードされるとします。この場合、処理途中に実行するセーブの間隔を10分以内にするには、ROWSを200,000(20,000行/分×10分間)に設定してください。

12.8.5 REDOログの最小限の使用

ダイレクト・ロードを大幅に高速化する1つの方法は、REDOログの使用を最小限に抑えることです。

それには3通りの方法があります。アーカイブを使用禁止にする方法、ロードをリカバリ不可能に指定する方法、ロードされるオブジェクトに対してSQLのNOLOGGINGパラメータを設定する方法です。この項では、すべての方法を説明します。

12.8.5.1 アーカイブの使用禁止

アーカイブが使用禁止の場合、ダイレクト・パス・ロードでは全体イメージのREDOログは生成されません。

SQLのARCHIVELOGおよびNOARCHIVELOGパラメータを使用して、アーカイブ・モードを設定します。

12.8.5.2 SQL*LoaderのUNRECOVERABLE句の指定

時間およびREDOログ・ファイルの領域を節約するには、データのロード時に制御ファイルでSQL*LoaderのUNRECOVERABLE句を使用します。

リカバリ不可能を指定したロードの場合は、ロードされたデータはREDOログ・ファイルに記録されません。かわりに、操作を無効にするために必要なREDOログ(無効REDOログ)が生成されます。

UNRECOVERABLE句は、ロード・セッション中にロードされたすべてのオブジェクト(データ・セグメントおよび索引セグメントの両方)に適用されます。このため、ロードされた表についてはメディア・リカバリはできません。ただし、他のユーザーが行ったデータベース変更のログは、引き続き記録されます。

ノート:

データ・ロードは記録されないため、必要な場合はロード後にデータのバックアップを取ってください。

UNRECOVERABLE句を指定してロードしたデータについてメディア・リカバリが必要になった場合、ロードしたデータ・ブロックには、論理的に破損したというマークが付けられます。

データをリカバリするには、データを削除して再作成します。データがリカバリ不能にならないように、データのロード後、すぐにバックアップを取ってください。

デフォルトでは、ダイレクト・パス・ロードはRECOVERABLEです。

次に、制御ファイルのUNRECOVERABLE句の指定例を示します。

UNRECOVERABLE
LOAD DATA
INFILE 'sample.dat'
INTO TABLE emp
(ename VARCHAR2(10), empno NUMBER(4));
12.8.5.3 SQL NOLOGGINGパラメータの設定

データまたは索引のセグメントにSQLのNOLOGGINGパラメータが設定されていると、そのセグメントに対する全体イメージのREDOログは使用できません(無効REDOログが生成されます)。

NOLOGGINGパラメータを使用すると、ログが記録されないオブジェクトに対しより優れた制御が可能です。

12.8.6 列配列の行数およびストリーム・バッファ・サイズの指定

列配列の行数によって、ストリーム・バッファが作成される前にロードされた行数を判断します。

STREAMSIZEパラメータで、クライアントからサーバーへ送ったデータのストリーム・サイズ(バイト単位)を指定します。

列配列の行数の値を指定するには、COLUMNARRAYROWSパラメータを使用します。ダイレクト・パスを使用してVARRAYをロードすると、COLUMNARRAYROWSパラメータはデフォルトで100に設定され、クライアント・オブジェクトのキャッシュ・スラッシングを回避します。

ダイレクト・パス・ストリーム・バッファのサイズを指定するには、STREAMSIZEパラメータを使用します。

これらのパラメータの最適値は、使用されるシステム、入力データ型およびOracleの列データ型に応じて異なります。独自の構成用に最適な値を使用することで、SQL*Loaderのログ・ファイルでの経過時間が少なくなります。

ノート:

ページングが過剰に発生すると、パフォーマンスが大幅に低下するため、ページング・アクティビティのプロセスを監視する必要があります。過剰なページングを回避するには、READSIZESTREAMSIZEおよびCOLUMNARRAYROWSの値を小さくする必要があります。

複数CPUシステムでダイレクト・パス・ロードを実行する場合、列配列の行数およびストリーム・バッファのサイズを指定すると、特に有効です。

12.8.7 DATE_CACHEの値の指定

ダイレクト・パス・ロード中に同じ日付またはタイムスタンプが何回も使用されるパフォーマンスを向上させるには、SQL*Loaderの日付キャッシュを使用します。

同じ日付値またはタイムスタンプ値のロードが何度も行われるダイレクト・パス・ロードを実行する場合、総ロード時間の大部分が日付およびタイムスタンプのデータの変換に使用される可能性があります。特に、複数の日付列がロードされる場合にこのような状況が発生します。この場合、SQL*Loaderの日付キャッシュを使用することによってパフォーマンスを向上できます。

日付キャッシュを使用すると、入力データ内に多数の重複する日付値が存在する場合、日付変換が実行される回数が減ります。この機能を使用すると、ロード中に予測される一意の日付の数を指定できます。

日付キャッシュは、デフォルトで使用可能です。日付キャッシュ機能を使用禁止にするには、0(ゼロ)に設定します。

デフォルトの日付キャッシュ・サイズは1000要素です。デフォルトのサイズを使用し、1000を超える一意の入力値がロードされると、日付キャッシュはこの表に対して自動的に使用禁止となります。これによって、過剰および不要なルックアップ時間によって、パフォーマンスが低下する可能性がなくなります。ただし、デフォルトを使用するかわりに0(ゼロ)以外の値を日付キャッシュに指定し、キャッシュ量がこの値を超えた場合、日付キャッシュは使用禁止になりません。最大値を超えた入力データは、適切な変換ルーチンによって明示的に変換されます。

日付キャッシュは、1つの表のみに対応付けできます。複数の表で日付キャッシュの共有はできません。次のすべての条件を満たす場合にのみ、表に対して日付キャッシュが作成されます。

  • DATE_CACHEパラメータが0(ゼロ)以外に設定されている

  • 表への格納のためにデータ型変換が必要な、1つ以上の日付値またはタイムスタンプ値(あるいはその両方)がロードされている

  • ダイレクト・パス・ロードでロードされている

日付キャッシュの統計はログ・ファイルに書き込まれます。これらの統計を使用して、次のとおりダイレクト・パス・ロードのパフォーマンスを向上できます。

  • キャッシュ・エントリの数がキャッシュ・サイズより小さく、キャッシュ・ミスがない場合は、キャッシュ・サイズをより小さい値に設定できます。

  • キャッシュ・ヒット(重複値が存在するエントリ)の数が小さく、キャッシュ・ミスの数が大きい場合は、キャッシュ・サイズを大きくする必要があります。キャッシュ・サイズを大きくしすぎると、過剰なページング、過度のメモリー使用量などの他の問題が発生する場合があります。

  • ほぼすべての入力日付値が一意の場合、日付キャッシュを使用してもパフォーマンスは向上しないため、使用する必要はありません。

    ノート:

    日付キャッシュがデフォルトで使用可能な場合、最大値を超えたため使用禁止になると、日付キャッシュの統計はSQL*Loaderのログ・ファイルに書き込まれません

キャッシュ・サイズを大きくしてもパフォーマンスが向上しない場合は、デフォルトの動作に戻すか、またはキャッシュ・サイズを0(ゼロ)に設定します。パフォーマンス全体の向上は、ロードされる他の列のデータ型によっても異なります。ロードされる日付列の総数がロードされる他のデータ型より大きい場合、パフォーマンスは大幅に向上します。

関連トピック

12.9 複数CPUシステムのダイレクト・パス・ロードの最適化

複数CPUシステムでダイレクト・パス・ロードを実行する場合、SQL*Loaderではデフォルトでマルチスレッドが使用されます。この場合の複数CPUシステムは、2つ以上のCPUを持つ単一のシステムとして定義されます。

マルチスレッド・ロードとは、可能な場合、列配列をストリーム・バッファに変換し、ストリーム・バッファ・ロードがパラレルで実行されることを表します。この最適化は、次の場合に最も効果的です。

  • 列配列が、ロード用に複数のダイレクト・パス・ストリーム・バッファを生成できる十分な大きさの場合。

  • 入力フィールドのデータ型からOracleの列データ型へのデータ変換が必要な場合。

    変換は、ストリーム・バッファのロード時にパラレルで実行されます。

この処理の状態は、次のログ部分の例で示しているように、SQL*Loaderのログ・ファイルに記録されます。

Total stream buffers loaded by SQL*Loader main thread:         47
Total stream buffers loaded by SQL*Loader load thread:        180
Column array rows:                                           1000
Stream buffer bytes:                                       256000

この例では、SQL*Loaderのロード・スレッドがメイン・スレッドをオフロードしています。これによって、ロード・スレッドがサーバーで現行のストリームをロードする一方で、メイン・スレッドは、次のストリーム・バッファを作成できます。

ロード・スレッドを使用して、できるだけ多くのストリーム・バッファ・ロードを実行することが目的です。これによって、列配列の行数の増加、またはストリーム・バッファのサイズの削減(あるいはその両方)を実現できます。SQL*Loaderのログ・ファイルの経過時間を監視することで、変更による効果を確認できます。詳細は、列配列の行数およびストリーム・バッファ・サイズの指定を参照してください。詳細は、「列配列の行数およびストリーム・バッファ・サイズの指定」を参照してください。

単一CPUシステム上では、最適化はデフォルトで無効になります。サーバーが他のシステム上にある場合は、マルチスレッドを手動で有効にするとパフォーマンスが向上します。

マルチスレッド・オプションを有効または無効にするには、SQL*LoaderのコマンドラインでMULTITHREADINGパラメータを使用するか、またはSQL*Loaderの制御ファイルにMULTITHREADINGパラメータを指定します。

12.10 索引メンテナンスの回避

従来型パスとダイレクト・パスの両方について、SQL*Loaderでは表のすべての既存の索引がメンテナンスされます。

索引のメンテナンスを回避するには、次のいずれかの方法を使用します。

  • ロードを始める前に索引を削除します。

  • ロードを始める前に、選択した索引または索引パーティションを索引使用禁止状態に設定し、SKIP_UNUSABLE_INDEXESパラメータを使用します。

  • SKIP_INDEX_MAINTENANCEパラメータを使用します(ダイレクト・パスの場合に限定されるため、注意して使用してください)。

索引のメンテナンスを回避すると、ダイレクト・パス・ロード中に必要な領域を最小限にできます。その方法は次のとおりです。

  • 一度に索引を作成できるため、各索引を別々に作成する場合に必要なソート用の(一時)セグメント領域を削減できます。

  • 索引の作成時に、索引セグメントは1つのみ存在します(これに対し、新しいキーを古いキーにマージして新しい索引を作成するときには、一時的に3つのセグメントが存在します)。

表の全行数に対してロードする行数が多い場合、索引のメンテナンスを避けることは合理的です。ただし、比較的少数の行を大きな表に追加する場合は、索引の再ソートに非常に時間がかかることがあります。そのような場合は、従来型パス・ロードを使用するか、SQL*LoaderのSINGLEROWパラメータを使用します。詳細は、「SINGLEROWオプション」を参照してください。

12.11 ダイレクト・パス・ロード、整合性制約およびトリガー

従来型パス・ロードと比較して、ダイレクト・パス・ロードを使用したトリガーの設定方法が異なる場合があります

従来型パス・ロードでは、行配列の挿入には標準SQL INSERT文を使用します。このとき、整合性制約および挿入トリガーは自動的に適用されます。ただし、ダイレクト・パスでデータをロードする場合は、SQL*Loaderでは一部の整合性制約およびすべてのデータベース・トリガーが使用禁止になります。

12.11.1 整合性制約

SQL*Loaderを使用したダイレクト・パス・ロード中に、一部の整合性制約は自動的に使用禁止になりますが、その他は使用禁止になりません。

整合性制約によってデータベースに関連付けられたビジネス・ルールがどのように強制されるかという概念をよく理解し、様々な手法を使用して表に無効な情報が入力されないようにするには、「データ整合性」を参照してください。

関連トピック

12.11.1.1 使用可能な制約

ダイレクト・パス・ロード中に、一部の制約は使用可能なままになります。

ダイレクト・パス・ロード時でも使用可能な制約は、次のとおりです。

  • NOT NULL

  • UNIQUE

  • 主キー制約(NOT NULL列における一意制約)

NOT NULL制約は列配列の作成時にチェックされます。NOT NULL制約に違反する行はすべて拒否されます。

ダイレクト・パス・ロード時にUNIQUE制約が使用可能であっても、その制約に違反する行もロードされます。(これは、そのような行が拒否される従来型パスとは異なります。)UNIQUE制約は、ダイレクト・パス・ロードの最後で索引が再作成されるときに検証されます。違反が検出されると、索引は索引使用禁止状態のままになります。詳細は、「使用禁止状態(Index Unusable)のままの索引」を参照してください。

12.11.1.2 使用禁止の制約

ダイレクト・パス・ロード中に、一部の制約は使用不可になります。

次の制約は、ダイレクト・パス・ロード時にデフォルトで自動的に使用禁止になります。

  • CHECK制約

  • 参照制約(外部キー)

EVALUATE CHECK_CONSTRAINTS句を指定すると、CHECK制約の自動的な使用禁止を変更できます。SQL*Loaderでは、ダイレクト・パス・ロード中にCHECK制約が評価されます。CHECK制約に違反する行はすべて拒否されます。次の例に、SQL*Loader制御ファイルでのEVALUATE CHECK_CONSTRAINTS句の使用方法を示します。

LOAD DATA 
INFILE * 
APPEND 
INTO TABLE emp 
EVALUATE CHECK_CONSTRAINTS 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
(c1 CHAR(10) ,c2) 
BEGINDATA 
Jones,10
Smith,20 
Brown,30
Taylor,40
12.11.1.3 制約を使用可能に戻す方法

SQL*Loaderのロードが完了すると、REENABLE句が指定されている場合、整合性制約が自動的に使用可能に戻されます。

REENABLE句の構文は次のとおりです。

DISABLED_CONSTRAINTSパラメータはオプションで、読みやすくするために使用します。EXCEPTIONS句が含まれている場合は、例外表(デフォルト名: EXCEPTIONS)がすでに存在していて、それに挿入できる必要があります。この表には、整合性制約のいずれかに違反したすべての行のROWID値が格納されます。また、違反があった制約名も格納されます。

例外表を作成する手順は、Oracle Database SQL言語リファレンスconstraintにあるexceptions_clauseを参照してください。

SQL*Loaderログ・ファイルには、使用禁止となっていた制約、および使用可能に戻された制約が記録され、エラーが原因で制約を使用可能に戻せなかった場合または検査できなかった場合はそのエラーが記録されます。さらに、ロードした表のそれぞれに指定された例外表の名前もログ・ファイルに書き込まれます。

REENABLE句を使用しない場合は、表のすべての行が検査されるときに制約を手動で使用可能に戻す必要があります。ここで新しいデータにエラーが見つかると、エラー・メッセージが生成されます。例外表を指定した場合は、違反のあった制約名と不良データのROWIDが、その表に書き込まれます。

REENABLE句を使用すると、制約を自動的に使用可能に戻し、新しい行すべてを検証できます。新しいデータにエラーが見つからなかった場合は、検証された制約に自動的にマークを付けられます。新しいデータにエラーが見つかった場合は、ログ・ファイルにエラー・メッセージが書き込まれ、SQL*Loaderによって制約の状態にENABLE NOVALIDATEというマークが付けられます。例外表を指定した場合は、違反のあった制約名と不良データのROWIDが、その表に書き込まれます。

ノート:

通常、表制約がENABLE NOVALIDATEの状態のままになっている場合、新しいデータは表へ挿入されますが、新しい無効なデータは挿入されません。ただし、SQL*Loaderのダイレクト・パス・ロードでは、この規則は施行されません。したがって、次のダイレクト・パス・ロードが無効なデータで実行される場合、無効なデータは挿入されますが、前述されたのと同じエラー・レポートおよび例外表の処理が実行されます。この例では、各ロードの前に外部表がクリーン・アウトされていない場合、その表には、重複するエントリが含まれます。重複するエントリは、次のような問合せを実行することによって、簡単に削除できます。

SELECT UNIQUE * FROM exceptions_table; 

ノート:

参照整合性の再検証は、表全体に対して実行する必要があります。そのため、少数の行を非常に大きい表にロードするときは、ダイレクト・パスではなく従来型パスを使用した方がパフォーマンスが向上することがあります。

12.11.2 データベース挿入トリガー

ダイレクト・パス・ロードが始まると、表挿入トリガーも使用禁止になります。

行のロードおよび索引の再作成が完了すると、使用禁止になっていたトリガーはすべて使用可能に戻されます。ログ・ファイルには、ロード時に使用禁止になっていたすべてのトリガーのリストが示されます。トリガーを使用可能に戻すときに1つでもエラーがあると、使用可能にできません。

整合性制約と異なり、挿入トリガーは、使用可能に戻っても表全体に対して再び適用されません。つまり、ダイレクト・パスでロードされた行に対しては、挿入トリガーは起動しません。ダイレクト・パスでロードした場合は、新しい行への挿入トリガーに相当する処理はすべて、アプリケーション側で実行する必要があります。

12.11.2.1 挿入トリガーの整合性制約への置換

アプリケーションは整合性制約を実行する場合、通常は挿入トリガーを使用します。

アプリケーションが使用する挿入トリガーのほとんどは単純なため、Oracleの自動整合性制約に置き換えることができます。

12.11.2.2 自動制約が使用できない場合

挿入トリガーは、Oracleの自動整合性制約に置き換えられない場合があります。

たとえば、挿入トリガーの中で表のルックアップ関数を使用して整合性チェックを行っている場合、自動制約は使用できません。これは、自動制約はカレント行における定数および列以外は参照できないためです。このようなトリガーと同じ処理を実現する方法が2つあります。この項ではその方法について説明します。

12.11.2.3 データベース・トリガーの準備

挿入トリガーまたは自動制約方法を使用する前に、Oracle Database表を準備する必要があります。

次に示す一般的なガイドラインに従って、表を準備してください。

  1. ロードの前に、表に1バイトまたは1文字分の列を追加します。この列は、各行が「旧データ」か「新データ」かを示すためのものです。
  2. この列の値がNULLの場合は「旧データ」を示すことにします。これは、NULL列であれば領域を使用せずに済むためです。
  3. ロード時にSQL*LoaderのCONSTANTパラメータを使用して、ロードしたすべての行に「新データ」を示すフラグを付けます。

この手順に従って準備すると、新しくロードした行が識別できるため、古い行に影響を与えずに新しいデータを操作できます。

12.11.2.4 更新トリガーの使用

一般に、挿入トリガーと同じ処理を実現する場合は、データベース更新トリガーを使用します。

これは最も単純な方法です。例外を呼び出さない挿入トリガーの場合は、常にこの方法を使用できます。

  1. 挿入トリガーと同じ処理を行う更新トリガーを作成します。

    トリガーをコピーします。「new.column_name」というすべての箇所を「old.column_name」に変更してください。

  2. 現行の更新トリガーがある場合は、それを新しい更新トリガーに置き換えます。
  3. 「新データ」のフラグをNULLに変更して、表を更新します。これによって、更新トリガーが起動します。
  4. 元の更新トリガーがある場合は、それをリストアします。

トリガーの動作によっては、この操作中に表に対する排他的更新アクセスが必要となる場合もあります。排他的更新アクセスを実行すると、他のユーザーが修正する行に、誤ってこのトリガーが適用されることはありません。

12.11.2.5 例外処理と同じ処理の実現

挿入トリガーの中で例外を呼び出している場合、それと同じ処理を行うには、さらに作業が必要です。

例外を呼び出すということは、表にその行を挿入しないということです。この処理を更新トリガーで実現するには、ロードした行に削除フラグを付けておく必要があります。

この場合、「新データ」列を削除フラグに使用することはできません。更新トリガーでは、その起動元である列を修正できないためです。したがって、表にもう1列追加する必要があります。ここで追加する列は、削除する行を示すためのものです。NULL値の場合は、行が有効であることを示します。挿入トリガーで例外を呼び出すと、常に、更新トリガーによって追加列にフラグが設定されます。これによって、その行が無効であることが示されます。

要約すると、挿入トリガーで例外を呼び出している場合は、次の条件を満たすと、同じ処理を更新トリガーで実現できます。

  • 表に列を2つ追加する(通常はNULL)。

  • 表を排他的に更新できる(必要な場合)。

12.11.2.6 ストアド・プロシージャの使用

挿入トリガーを使用すると例外が発生する場合は、ストアド・プロシージャを使用して挿入トリガーと同じ処理を実現することを検討してください。

次に示すプロシージャは、どのような場合でも使用できますが、その実装はより複雑になります。このプロシージャは、挿入トリガーで例外を呼び出すときに使用できます。そのとき、2番目の列を追加する必要はありません。また、更新トリガーとは処理が異なるため、表に対する排他的アクセス権限がなくても使用できます。
  1. 挿入トリガーと同じ処理を実現するストアド・プロシージャを作成します。
    1. 表から新しい行をすべて選択するように、カーソルを宣言します。
    2. 処理ループの中でカーソルをオープンし、1回に1行ずつフェッチします。
    3. 挿入トリガーでの操作を実行します。
    4. 操作が正常に終了した場合は、「新データ」のフラグをNULLに変更します。
    5. 操作が失敗した場合は、「新データ」のフラグを「不良データ」に変更します。
  2. SQL*Plusなどの管理ツールを使用して、このストアド・プロシージャを実行します。
  3. プロシージャの実行後、表の中に「不良データ」フラグの付いた行がないかどうかを調べます。
  4. 不良の行を更新または削除します。
  5. 挿入トリガーを使用可能に戻します。

12.11.3 永続的に使用禁止のトリガーおよび制約

SQL*Loaderでは、トリガーおよび制約を使用禁止にするために、ロードされる表にいくつかのロックを獲得する必要があります。

競合するプロセスが表のトリガーまたは制約を使用可能にしているときに、SQL*Loaderでその表のトリガーまたは制約を使用禁止にしようとした場合、SQL*Loaderではその表に関して排他的アクセス権を獲得することはできません。

この場合、SQL*Loaderでは、できるかぎり問題のないように処理が実行されます。ロード終了前に、使用禁止のトリガーおよび制約を使用可能に戻そうとします。ただし、表ロックが原因でSQL*Loaderの処理を継続できなくなった場合は、SQL*Loaderでトリガーや制約を使用可能にする処理も実行されないことがあります。この場合、トリガーおよび制約は、手動で使用可能にするまで永続的に使用できない状態になります。

このような状況はまれですが、発生する可能性はあります。このような状況を回避するには、ダイレクト・ロードの処理中は、表のトリガーまたは制約を使用可能にするアプリケーションを実行しないことをお薦めします。

適切なロックの獲得に失敗したことによってダイレクト・ロードが終了した場合は、ログを確認してください。ログには、使用禁止のすべてのトリガーおよび制約と、それらを使用可能に戻すための各試行が示されます。SQL*Loaderによって使用可能に戻されなかったすべてのトリガーおよび制約は、『Oracle Database SQL言語リファレンス』で説明するALTER TABLE文のENABLE句を使用して、手動で使用可能にする必要があります。

12.11.4 従来型パスの同時ロードによるパフォーマンスの向上

トリガーまたは整合性制約の問題があっても、より高速なロードを実現する場合は、従来型パスによる同時ロードの使用を考えてください。

つまり、複数CPUシステムで同時に複数のセッションでロードを実行します。入力データ・ファイルを論理レコードの境界で別々のファイルに分割し、それらの各入力データ・ファイルを従来型パス・ロード・セッションでロードします。このロードには、次のような特長があります。

  • 複数CPUシステムでの単一従来型パス・ロードよりは速くなりますが、ダイレクト・ロードほど速くはありません。

  • トリガーが起動されて整合性制約がロードされた行に適用され、標準DML実行ロジックによって索引がメンテナンスされます。

12.12 ダイレクト・パス・ロードのパフォーマンスの最適化

SQL*Loaderダイレクト・パス・ロードの高速実行を可能にし、使用する領域を減らす方法を学習します。

12.12.1 自動および手動パラレル・ダイレクト・パス・ロードの制限事項

SQL*Loaderクライアントを使用して手動でダイレクト・パス・ロードをパラレルで実行する場合は、ここで示す制限事項に注意してください。

ノート:

Oracle Database 23c向けSQL*Loaderクライアント以降では、SQL*Loaderクライアントで、Oracle Database 12cリリース2 (12.2)以降のすべてのOracle Databaseリリースからのダイレクト・パス・ロードをサポートできます。この機能は、リリース23c向けのSQL*Loader Instant Clientで使用できます。一般に、自動パラレル・ダイレクト・パス・ロード・プロシージャを使用する必要があります。特に明記されている場合を除き、ここで示す制限事項は、手動および自動の両方のパラレル・ロードに適用されます。

パラレル・ダイレクト・パス・ロードを実行する場合は、次の制限事項が適用されます。

  • グローバル索引は、ロードでは保持されません。デフォルトでは、ローカル索引は保持されます。
  • パラレル・ロードの場合は、ROWSを指定できません。これを行おうとすると、SQL*Loaderで、「SQL*Loader-826: ROWSパラメータは、degree_of_parallelismパラメータを使用したパラレル・ダイレクト・パス・ロードではサポートされていません。」というエラーが返されます。
  • 表内の主キーの値にNULLを指定することはできません。

ノート:

自動パラレル・ダイレクト・パス・ロードを使用する場合は、ロードの開始時に実行されるTRUNCATEまたはREPLACEロード・オプションを使用できます。

SQL*Loaderでは、ロードが開始される前に次の制限およびトリガーが自動的に無効化され、ロードの完了後にそれらが再有効化されます。

  • 参照整合性制約
  • トリガー
  • CHECK制約(ENABLE_CHECK_CONSTRAINTS制御ファイル・オプションが使用されている場合を除く)

12.12.2 SQL*Loaderのパラレル・データ・ロード・モデルについて

データのロードに必要な所要時間を最小限にするために使用される、同時処理の3つの基本モデルがあります。

同時実行性モデルは次のとおりです。

  • 従来型パスによる同時ロード
  • ダイレクト・パス・ロードによるセグメント間同時処理
  • ダイレクト・パス・ロードによるセグメント内同時処理

Oracle Database 21c以降では、SQL*LoaderパラメータCREDENTIALを使用して、オブジェクト・ストアへの読取りアクセスを有効にする資格証明を提供できます。オブジェクト・ストアからのパラレル・ロードがサポートされています。

また、Oracle Database 23c以降では、SQL*Loaderを使用した従来型パス・ロードとダイレクト・パス・ロードのどちらでも、シャード表と非シャード表の自動パラレル・ロードを有効にできます。

12.12.3 従来型パスによる同時ロード

このトピックでは、従来型パスによる同時ロードの使用について説明します。

同時に複数の従来型パス・ロード・セッションを実行する方法の詳細は、「従来型パスの同時ロードによるパフォーマンスの向上」を参照してください。同一または異なるオブジェクトを制限なしで同時にロードする場合に、この方法を使用できます。

12.12.4 ダイレクト・パスによるセグメント間同時処理

セグメント間同時処理は、異なるオブジェクトを同時にロードする場合に使用できます。

この方法は、異なる表の同時ダイレクト・パス・ロード、または同じ表の異なるパーティションの同時ダイレクト・パス・ロードに適用できます。

1つのパーティションのダイレクト・パス・ロードを行う場合は、次のことを考慮します。

  • ローカル索引は、ロードによってメンテナンスされます。

  • グローバル索引は、ロードではメンテナンスできません。

  • 参照整合性およびCHECK制約は使用禁止にする必要があります。

  • トリガーは使用禁止にする必要があります。

  • 入力データは事前にパーティション化する必要があります(パーティション化しない場合、多くのレコードが拒否され、パフォーマンスが低下します。)

12.12.5 ダイレクト・パスによるセグメント内同時処理

SQL*Loaderでは、複数のセッションを同時に実行して、同一の表またはパーティション表の同一パーティションに対してダイレクト・パス・ロードを実行できます。

複数のSQL*Loaderセッションを実行すると、システムで使用可能なリソースを与えられればダイレクト・パス・ロードのパフォーマンスが向上します。

このデータ・ロード方法は、DIRECTおよびPARALLELパラメータにTRUEを設定することによって使用でき、「パラレル・ダイレクト・パス・ロード」とも呼ばれます。

並列化はユーザーによって管理されるものだということを理解しておいてください。PARALLELパラメータにTRUEを設定した場合、複数の同時ダイレクト・パス・ロード・セッションのみが可能になります。

12.12.6 手動パラレル・ダイレクト・パス・ロードの制限事項

パラレル・ダイレクト・パス・ロードを手動で構成する場合は、手動パラレル・ダイレクト・パス・ロードに適用される制限事項を確認し、それらを把握しておいてください。

手動パラレル・ダイレクト・パス・ロードには次の制限事項があります。

  • ローカル索引もグローバル索引もロードによってメンテナンスできません。

  • 行は追加(APPEND)のみできます。REPLACETRUNCATEおよびINSERTは使用できません(これは、手動パラレル・ダイレクト・パス・ロードでは個々のロード間に整合性がないためです)。パラレル・ロードの前に表を切り捨てる必要がある場合は、手動で行ってください。

さらに、パラレル・ダイレクト・パス・ロードでは次のオブジェクトを使用禁止にする必要があります。これらを使用禁止にするための操作は不要です。SQL*Loaderではロードの開始前にこれらを使用禁止にし、ロードの完了後にこれらを使用可能に戻します。

  • 参照整合性制約

  • トリガー

  • CHECK制約(ENABLE_CHECK_CONSTRAINTS制御ファイル・オプションが使用される場合を除く)

単一パーティションに手動パラレル・ダイレクト・パス・ロードが適用されている場合は、まず、データをパーティション化する必要があります(そうしないと、パーティション不一致によるレコード拒否のオーバーへッドのため、ロード速度が遅くなります)。

12.12.7 手動での複数のSQL*Loaderセッションの開始

データのダイレクト・パス・パラレル・ロードを手動で開始することにした場合は、同じ表でダイレクト・ロードを実行するすべてのセッションについて、PARALLELTRUEに設定する必要があります。

構文

PARALLELTRUEに設定すると、各SQL*Loaderセッションに、入力として、異なるデータ・ファイルが取得されます。構文:

PARALLELは、コマンドラインで、またはパラメータ・ファイル内で指定できます。また、OPTIONS句を使用して制御ファイルに指定することもできます。

たとえば、1つの表について3つのSQL*Loaderダイレクト・パス・ロード・セッションを開始するには、オペレーティング・システムのプロンプトで、次の各コマンドを実行します。コマンドをそれぞれ入力した後に、パスワードを入力するように要求されます。

sqlldr USERID=scott CONTROL=load1.ctl DIRECT=TRUE PARALLEL=TRUE
sqlldr USERID=scott CONTROL=load2.ctl DIRECT=TRUE PARALLEL=TRUE
sqlldr USERID=scott CONTROL=load3.ctl DIRECT=TRUE PARALLEL=TRUE

このコマンドは、別々のセッションで実行するか、またはオペレーティング・システムがサポートしている場合には別々のバックグラウンド・ジョブとして実行してください。複数の制御ファイルを使用していることに注意してください。手動パラレル・ダイレクト・パス・ロードの場合、複数の制御ファイルを使用すると、ダイレクト・パス・ロードに使用するファイルをより柔軟に指定できます。

ノート:

パラレル・ロード時には、索引はメンテナンスされません。ロード完了後に、索引をすべて手動で(再)作成または再構築する必要があります。パラレル・ロード後に大きな索引を構築する場合、パラレル索引作成機能またはパラレル索引再構築機能を使用すると処理を高速化できます。

手動パラレル・ロードを実行すると、SQL*Loaderによって、同時実行セッションごとに一時セグメントが作成されます。それらのセグメントは、ロード完了時にマージされます。マージによって作成されたセグメントは、セグメントの最高水位標より上にあるデータベースの既存のセグメントに追加されます。各ローダー・セッションの各セグメントで使用された最後のエクステントは、空き領域をすべて切り捨ててから、SQL*Loaderセッションの他のエクステントと組み合せることができます。

12.12.8 手動パラレル・ダイレクト・パス・ロードのパラメータ

パラレル・ダイレクト・パス・ロードを手動で実行する場合は、ローダーによって割り当てられる一時セグメントの属性の指定に使用できる、複数のオプションがあります。

ローダーのオプションは、FILEおよびSTORAGEパラメータで指定します。これらのパラメータは、手動パラレル・ロードの場合のみ有効です。

12.12.8.1 FILEパラメータを使用した一時セグメントの指定

最大の入出力スループットを得るために、同時実行のダイレクト・パス・ロード・セッションで、各ファイルを別のディスクに置いて使用することをお薦めします。

SQL*Loader制御ファイルでは、ロードされるオブジェクト(表またはパーティション)の表領域にある有効なデータ・ファイルであれば、OPTIONS句のFILEパラメータを使用してファイル名を指定できます。

たとえば:

LOAD DATA
INFILE 'load1.dat'
INSERT INTO TABLE emp
OPTIONS(FILE='/dat/data1.dat')
(empno POSITION(01:04) INTEGER EXTERNAL NULLIF empno=BLANKS
...

同時実行する各SQL*Loaderセッションのコマンドラインでも、FILEパラメータを指定できます。ただし、その指定は、そのセッションでロードされるすべてのオブジェクトにグローバルに適用されます。

12.12.8.1.1 FILEパラメータの使用

このトピックでは、FILEパラメータの使用について説明します。

パラレル・ダイレクト・パス・ロードでは、Oracle DatabaseのFILEパラメータに次の制限があります。

  • 非パーティション表の場合: 指定されたファイルは、ロードする表と同じ表領域に存在する必要があります。

  • パーティション表の1つのパーティションをロードする場合: 指定したファイルは、ロードするパーティションの表領域に存在する必要があります。

  • パーティション表の表全体をロードする場合: 指定されたファイルは、ロードするすべてのパーティションと同じ表領域に存在する必要があります。つまり、すべてのパーティションは同じ表領域に存在する必要があります。

12.12.8.1.2 STORAGEパラメータの使用方法

STORAGEパラメータを使用して、パラレル・ダイレクト・パス・ロード用に割り当てられる一時セグメントの記憶域属性を指定できます。

STORAGEパラメータが使用されない場合は、ロードされるオブジェクト(表、パーティション)が存在するセグメントの記憶域属性が使用されます。また、STORAGEパラメータが指定されてない場合は、SQL*LoaderでEXTENTS用にデフォルトの2KBが使用されます。

たとえば、STORAGEパラメータを指定するためには、次のOPTIONS句が使用されます。

OPTIONS (STORAGE=(INITIAL 100M NEXT 100M PCTINCREASE 0))

STORAGEパラメータを使用できるのは、SQL*Loader制御ファイル内のみでコマンドラインでは使用できません。STORAGEパラメータは、PCTINCREASEを0(ゼロ)に設定する、INITIALまたはNEXT値を設定する以外には、使用しないでください。暗黙的に無視される可能性があります。

12.12.9 パラレル・ダイレクト・パス・ロード後の制約の使用可能化

すべてのデータのロード完了後に、制約およびトリガーを手動で使用可能にしてください。

それぞれのSQL*Loaderセッションで、ダイレクト・パス・ロードの後に表の制約が使用可能に戻されることがあるため、あるセッションで、他のセッションがデータのロードを終える前に、制約が使用可能に戻される可能性があります。この場合、ロードを完了する最初のセッションでは、残りのセッションで表のロックが共有されているため、制約を使用可能にできなくなります。

ダイレクト・パス・ロードの後、一部の制約が使用可能に戻っていない可能性があるため、ロードの完了後、制約の状態を調べ、制約が使用可能になったことを確認する必要があります。

12.12.10 主キー制約および一意キー制約

このトピックでは、主キー制約および一意キー制約の使用について説明します。

PRIMARY KEY制約およびUNIQUE KEY制約が有効である場合、表に索引が作成されます。表が非常に大きい場合は、ダイレクト・パス・ロード後に索引を使用可能にするまでに非常に長い時間がかかる可能性があります。ロード後に、これらの制約を手動で有効にしてください(また、自動で有効にする機能を指定しないでください)。これによって、必要な索引をパラレルに手動で作成し、制約を有効にするまでの時間を節約できます。

12.13 一般的なパフォーマンス改善のヒント

パラレル・データ・ロードでSQL*Loaderを使用する場合に一般的なパフォーマンスの改善を有効にする方法について説明します。

ロードするデータの形式について制御が可能な場合は、次に示すヒントを利用してロード・パフォーマンスを改善できます。

  • 論理レコードの処理を効率化します。

    • 物理レコードと論理レコードの1対1のマップを使用します(CONTINUEIFおよびCONCATENATEを使用しない)。

    • ソフトウェアで物理レコードの境界を簡単に判断できるようにします。ファイル処理オプション文字列「FIX nnn」または「VAR」を使用します。ほとんどのプラットフォーム(UNIX、NTなど)では、デフォルト(ストリーム・モード)を使用する場合、ローダーで各物理レコードをスキャンしてレコード終了記号(改行文字)を探す必要があります。

  • フィールド設定を効率化します。

    フィールド設定とは、データ・ファイルのフィールドを、ロードされる表の対応する列にマップする処理です。マップ機能は、制御ファイルのフィールド記述によって制御されます。フィールド設定は(データ変換とともに)、ほとんどのロードでCPUサイクルを最も使用する処理です。

    • デリミタ付きのフィールドを使用しないようにします。固定位置のフィールドを使用します。デリミタ付きフィールドを使用すると、ローダーで入力データをスキャンしてデリミタを見つけなければなりません。固定位置フィールドを使用すると、フィールド設定は単純なポインタの算出によって(非常に速く)行われます。

    • (PRESERVE BLANKSを使用する)必要がない場合は、空白を切り捨てないでください。

  • 変換を効率化します。

    SQL*Loaderでは、文字セット変換、データ型変換などのいくつかの変換が行われます。このような変換が行われない場合、処理は最も速くなります。

    • 可能な場合は、シングルバイト文字セットを使用します。

    • 文字セット変換はできるだけ行わないようにします。SQL*Loaderでは、次の4つの文字セットがサポートされています。

      • クライアント文字セット(クライアントsqlldrプロセスのNLS_LANG)
      • データ・ファイル文字セット(通常、クライアント文字セットと同じ)
      • データベース文字セット
      • データベース文字セット

      すべての文字セットが同じ場合、パフォーマンスは最適化されます。ダイレクト・パスでは、データ・ファイル文字セットとデータベース・サーバー文字セットが同じである場合、最適なパフォーマンスが得られます。文字セットが同じ場合、文字セット変換用バッファは割り当てられません。

  • ダイレクト・パス・ロードを使用します。

  • SORTED INDEXS句を使用します。

  • NULLIF句およびDEFAULTIF句は必要な場合以外は使用しないようにします。これらの句は、関連する句を持つ各列にロードされるすべての行について、評価される必要があります。

  • 可能な場合は、パラレル・ダイレクト・パス・ロードおよびパラレル索引作成を使用します。

  • CONCATENATE句およびCOLUMNARRAYROWS句の両方に大きい値を指定する場合は、パフォーマンスへの影響に注意します。