11.1 LOBパフォーマンスのガイドライン
この項では、データ・インタフェースまたはLOB APIを介してLOBを使用する際のパフォーマンスのガイドラインを示します。
LOBには、データ・インタフェースを使用するかLOB APIを使用してアクセスできます。
- すべてのLOB
この項では、LOBの使用時に良好なパフォーマンスを実現するためのガイドラインについて説明します。 - 永続LOB使用時のパフォーマンスのガイドライン
前述のすべてのLOBに適用可能なパフォーマンスのガイドラインに加えて、永続LOB使用時のパフォーマンスのガイドラインを次に示します。 - 一時LOB
前述のすべてのLOBに適用可能なパフォーマンス・ガイドラインに加えて、一時LOBの使用に関するガイドラインを次に示します。 - Value LOB
Value LOBは一時LOBです。したがって、一時LOB記憶域に関するすべてのガイドラインが、値LOBにも当てはまります。
親トピック: パフォーマンスのガイドライン
11.1.1 すべてのLOB
この項では、LOBの使用時に良好なパフォーマンスを実現するためのガイドラインについて学習します。
- I/Oを最小限にするには:
- ブロック境界でデータの読取りおよび書込みを行います。これにより、UNDO生成を最小限にするなどの様々な方法でI/Oが最適化されます。一時LOBおよびSecureFile LOBの場合、表領域ブロック・サイズの使用可能データ領域は、PLSQLでは
DBMS_LOB.GETCHUNKSIZE
というAPI、OCIではOCILobGetChunkSize()
によって戻されます。ループで書き込む場合は、1つのデータベース・ブロックに書き込む必要があるすべての内容を1回の書込みコールで書き込むようにコードを設計し、それによって、同じブロックに連続的に書き込まれることがないようにします。 - 一度に大量のデータの読取りおよび書込みを行います。
- 前述の2つの推奨事項を組み合せて行うには、
DBMS_LOB.GETCHUNKSIZE/OCILobGetChunkSize()
APIによって返されたデータベース・ブロック・サイズに大きい整数を乗算したサイズで、読取りおよび書込みを行います。
- ブロック境界でデータの読取りおよび書込みを行います。これにより、UNDO生成を最小限にするなどの様々な方法でI/Oが最適化されます。一時LOBおよびSecureFile LOBの場合、表領域ブロック・サイズの使用可能データ領域は、PLSQLでは
- サーバーとのラウンドトリップの回数を最小限にするには:
- LOBデータの最大サイズを把握しており、LOB全体を読み取るか書き込む場合は、次に説明するように、データ・インタフェースを使用します。LOB全体のサイズを単一のバッファとして割り当てるか、ピース単位方式またはコールバック方式を使用することができます。
- 読取り操作の場合は、OCIで
OCIDefineByPos()
関数、JDBCでDefineColumnType()
関数を使用して、LOBを文字型またはバイナリ型として定義します。 - 書込み操作の場合は、OCIで
OCIBindByPos()
関数、JDBCでsetString()
メソッドまたはsetBytes()
メソッドを使用して、LOBを文字型またはバイナリ型としてバインドします。
- 読取り操作の場合は、OCIで
- それ以外の場合は、次のようにLOB APIを使用します。
- 読取りにはLOBのプリフェッチを使用します。その列に大部分のLOB値を含めることができるようにLOBプリフェッチ・サイズを定義します。
-
OCILobRead2
操作またはOCILobWrite2
操作を使用する際にピース単位方式またはコールバック方式を使用し、サーバーとのラウンドトリップを最小限にします。
- LOBデータの最大サイズを把握しており、LOB全体を読み取るか書き込む場合は、次に説明するように、データ・インタフェースを使用します。LOB全体のサイズを単一のバッファとして割り当てるか、ピース単位方式またはコールバック方式を使用することができます。
関連項目:
永続LOB用のデータ・インタフェース親トピック: LOBパフォーマンスのガイドライン
11.1.2 永続LOB使用時のパフォーマンスに関するガイドライン
前述の、すべてのLOBに当てはまるパフォーマンス・ガイドラインに加え、ここでは、永続LOBを使用する際のパフォーマンス・ガイドラインを示します。
- 1つのトランザクション内でコールを連続して行うことで、単一のLOBへの書込みを最大限にします。DML文をインターリーブすると、キャッシュの効率が最大に達するのが防止されます。
- セーブポイントの作成やコミットは頻繁に実行しないでください。これにより、書込みの間のキャッシュの利点がなくなります。
ノート:
永続LOBの格納にはSecurefile LOBを使用することをお薦めしています。そのため、この章では、Securefileストレージのみに焦点を当てます。永続LOBに関する文脈では、LOBとは、他に示されていないかぎり、Securefile LOBを意味します。親トピック: LOBパフォーマンスのガイドライン
11.1.3 一時LOB
前述のすべてのLOBに適用可能なパフォーマンス・ガイドラインに加えて、一時LOBの使用に関するガイドラインを次に示します。
-
一時LOBは、サイズに応じてPGAメモリーまたは一時表領域に存在します。アプリケーションで使用される一時LOB用に十分なPGAメモリーおよび一時表領域があることを確認してください。
-
デフォルトのシステム表領域のかわりに、一時LOB記憶域に別の一時表領域を使用しますこれによって、データを永続LOBから一時LOBにコピーする場合のデバイスの競合を回避します。
アプリケーションでLOBにSQLセマンティクスまたはPL/SQLセマンティクスを使用すると、多くの一時LOBがサイレントに作成されます。これらの一時LOBを格納するPGAメモリーおよび一時表領域が、アプリケーションに十分な大きさであることを確認してください。特に、これらの一時LOBが暗黙的に作成されるのは、次の事項を使用または実行する場合です。
-
LOBに対するSQLファンクション
-
LOBに対するPL/SQL組込み文字ファンクション
-
VARCHAR2
からCLOB
、RAW
からBLOB
への変数割当て。 -
LONG
からLOB
への移行
-
-
SQL問合せおよびPL/SQLプログラムから戻された一時LOBを解放します
PL/SQL、C (OCI)、Javaおよび他のプログラム・インタフェースでは、SQL問合せの結果またはPL/SQLプログラムの実行によって、LOBのオペレーション・コールおよびファンクション・コールに対して一時LOBが戻されます。たとえば:
SELECT substr(CLOB_Column, 4001, 32000) FROM ...
PL/SQLで問合せが実行される場合、戻された一時LOBは、PL/SQLプログラム・ブロックの終了時に自動的に解放されます。任意の時点で、明示的に一時LOBを解放することもできます。OCIおよびJavaでは、戻された一時LOBを明示的に解放する必要があります。
SQL問合せから戻された一時LOBの割当てを適切に解除しないと、パフォーマンスが低下する可能性があります。
-
PL/SQLでは、可能なかぎりNOCOPYを使用して、参照によって一時LOBパラメータを渡します。
関連項目:
参照によるパラメータの受渡しおよびパラメータのエイリアシングの詳細は、Oracle Database PL/SQL言語リファレンスを参照してください
-
CACHEパラメータをtrueに設定して作成された一時LOBは、バッファ・キャッシュ内を移動し、ディスク・アクセスを回避します。
- すべてのオープン・セッションでの一時LOBの使用を監視するための
v$temporary_lobs
ビューが用意されています。例:SQL> select * from v$temporary_lobs; SID CACHE_LOBS NOCACHE_LOBS ABSTRACT_LOBS CON_ID ---------- ---------- ------------ ------------- ---------- 141 2 3 4 0 146 0 0 1 0 148 0 0 1 0
次に、出力の解釈を示します。SID
列は、セッションIDです。CACHE_LOBS
列は、CACHEがオンになっている一時表領域にセッション141の一時LOBが現在2つあることを示しています。NOCACHE_LOBS
列は、CACHEがオフになっている一時表領域にセッション141の一時LOBが現在3つあることを示しています。ABSTRACT_LOBS
列は、セッション141のPGAメモリーに現在4つの一時LOBがあることを示しています。CON_ID
列は、プラガブル・データベースのコンテナIDです。
-
最適なパフォーマンスを実現するために、一時LOBでは、読取り時参照、書込み時コピーのセマンティクスが使用されます。一時LOBロケータが別のロケータに割り当てられる場合、物理LOBデータはコピーされません。どちらかのLOBロケータを使用する以降のREAD操作では、同じ物理LOBデータが参照されます。割当て後の最初のWRITE操作では、LOB値のセマンティクスを保ち、各ロケータが確実に一意のLOB値を指すように、物理LOBデータがコピーされます。
PL/SQLでは、読取り時参照、書込み時コピーのセマンティクスは次のように示されます。
LOCATOR1 BLOB; LOCATOR2 BLOB; DBMS_LOB.CREATETEMPORARY (LOCATOR1,TRUE,DBMS_LOB.SESSION); -- LOB data is not copied in this assignment operation: LOCATOR2 := LOCATOR; -- These read operations refer to the same physical LOB copy: DBMS_LOB.READ(LOCATOR1, ...); DBMS_LOB.GETLENGTH(LOCATOR2, ...); -- A physical copy of the LOB data is made on WRITE: DBMS_LOB.WRITE(LOCATOR2, ...);
OCIでは、LOBロケータおよびデータの値セマンティクスを保証するために、
OCILobLocatorAssign()
を使用してLOBデータと一時LOBロケータがコピーされます。OCILobLocatorAssign()
の場合、サーバーへのラウンドトリップは発生しません。物理的な一時LOBコピーは、次のように、LOB更新APIと同じラウンドトリップでLOBの更新が発生する場合に実行されます。OCILobLocator *LOC1; OCILobLocator *LOC2; OCILobCreateTemporary(... LOC1, ... TRUE,OCI_DURATION_SESSION); /* No round-trip is incurred in the following call. */ OCILobLocatorAssign(... LOC1, LOC2); /* Read operations refer to the same physical LOB copy. */ OCILobRead2(... LOC1 ...) /* One round-trip is incurred to make a new copy of the * LOB data and to write to the new LOB copy. */ OCILobWrite2(... LOC1 ...) /* LOC2 does not see the same LOB data as LOC1. */ OCILobRead2(... LOC2 ...)
LOB値セマンティクスが意図されていない場合は、次のコード・スニペットに示すように、両方のロケータが同じデータを指すようにCポインタ割当てを使用できます。
OCILobLocator *LOC1; OCILobLocator *LOC2; OCILobCreateTemporary(... LOC1, ... TRUE,OCI_DURATION_SESSION); /* Pointer is copied. LOC1 and LOC2 refer to the same LOB data. */ LOC2 = LOC1; /* Write to LOC2. */ OCILobWrite2(...LOC2...) /* LOC1 sees the change made to LOC2. */ OCILobRead2(...LOC1...)
-
一時LOBに対してOCI_OBJECTモードを使用します。
LOB割当てでの一時LOBのパフォーマンスを向上させるには、
OCILobLocatorAssign()
に対してOCI_OBJECT
モードを使用します。OCI_OBJECT
モードでは、データベースはディープ・コピー回数を最小限にしようとします。そのため、OCI_OBJECT
モードでソース一時LOBに対してOCILobLocatorAssign()
が実行された後、ソース・ロケータおよび宛先ロケータは、いずれかのLOBロケータにより変更されるまで同一LOBを指すようになります。
親トピック: LOBパフォーマンスのガイドライン
11.1.4 値LOB
値LOBは一時LOBです。したがって、一時LOB記憶域に関するすべてのガイドラインが、値LOBにも当てはまります。
クライアント側で、値LOBについて、LOB読取りサイズの80%以上に対応できる大きさのLOBプリフェッチ・サイズを設定することをお薦めします。
親トピック: LOBパフォーマンスのガイドライン