OracleLOBの動作は次のとおりです。
LOBは、次の場合にインラインで保存されます。
(
The size is lower or equal than 3964
AND
ENABLE STORAGE IN ROW has been defined in the LOB storage clause
) OR (
The value is NULL
)
LOBは、次の場合に行外に格納されます。
(
The value is not NULL
) AND (
Its size is higher than 3964
OR
DISABLE STORAGE IN ROW has been defined in the LOB storage clause
)
現在、パフォーマンスに影響を与える可能性のある問題はこれだけではありません。
LOBが最終的にインラインに格納されない場合、Oracleのデフォルトの動作では、LOBのキャッシュは回避されます(インラインLOBのみが、行の他のフィールドとともにバッファキャッシュにキャッシュされます)。インライン化されていないLOBもキャッシュするようにOracleに指示するには、LOBを定義するときにCACHEオプションを使用する必要があります。
デフォルトの動作は、ENABLE STORAGE IN ROWおよびNOCACHEです。これは、小さいLOBがインライン化され、大きいLOBはインライン化されない(そしてキャッシュされない)ことを意味します。
最後に、通信プロトコルレベルでのパフォーマンスの問題もあります。通常のOracleクライアントは、LOBごとに2つの追加ラウンドトリップを実行してそれらをフェッチします。1つはLOBのサイズを取得し、それに応じてメモリを割り当てます。もう1つはデータ自体をフェッチします(LOBが小さい場合)
これらの追加のラウンドトリップは、配列インターフェイスを使用して結果を取得する場合でも実行されます。 1000行を取得し、配列サイズが十分に大きい場合、行を取得するために1ラウンドトリップ、LOBのコンテンツを取得するために2000ラウンドトリップを支払うことになります。
ないことに注意してください LOBがインラインで格納されているかどうかによって異なります。それらは完全に異なる問題です。
プロトコルレベルで最適化するために、Oracleは、1回のラウンドトリップで複数のLOBをフェッチする新しいOCI動詞を提供しました(OCILobArrayRead)。 JDBCに同様の何かが存在するかどうかはわかりません。
もう1つのオプションは、大きなRAW/VARCHAR2であるかのようにクライアント側でLOBをバインドすることです。これは、LOBの最大サイズを定義できる場合にのみ機能します(バインド時に最大サイズを指定する必要があるため)。このトリックにより、余分なラウンドトリップが回避されます。LOBはRAWまたはVARCHAR2のように処理されます。 LOBを多用するアプリケーションでよく使用します。
ラウンドトリップの数が最適化されると、状況に合わせてパケットサイズ(SDU)のサイズをネット構成で変更できます(つまり、大きなラウンドトリップの数が制限されます)。 「SQL*Netより多くのデータをクライアントに」および「SQL*Netより多くのデータをクライアントから」待機イベントを減らす傾向があります。