Oracle LOB入門|BLOB・CLOBの使い分けとDBMS_LOB・SecureFiles実践
結論|BLOB・CLOBを迷わず選ぶための判断基準
Oracle LOBを選ぶときは、データが文字かバイナリかだけでなく、更新方法、文字コード、バックアップ、配信方法まで確認することが重要です。
最初に選定基準を整理しておくと、後から型変換や保存方式の見直しが必要になるリスクを抑えられます。
この章の比較軸を押さえれば、型名ではなく運用要件から選べるようになります。
BLOB・CLOB・NCLOB・BFILEの早見表
最初に四つの型の役割を整理すると、保存後の設計変更やアプリ側の変換処理を減らしやすくなります。
| 型 | 主な対象 | 保存場所 | 更新 | 主な注意点 |
|---|---|---|---|---|
| BLOB | 画像、PDF、圧縮ファイルなどのバイナリ | データベース内 | 可能 | 文字コードを意識せずバイト列として扱う |
| CLOB | 大容量の文章、JSON、XMLなどの文字 | データベース内 | 可能 | データベース文字セットで扱う |
| NCLOB | 各国語を含む大容量文字 | データベース内 | 可能 | 各環境の各国語文字セットを確認する |
| BFILE | OS上の外部ファイル | データベース外 | データベースからは読取り中心 | ファイルの存在、権限、バックアップを別管理する |
型名だけで判断せず、データをどのAPIで読み書きするかまで想定して選ぶことが重要です。
将来の検索、変換、配信方法も確認しておくと、保存後に別の型へ移行する手間を減らせます。
文字・バイナリ・外部ファイルで選ぶ基本フロー
文章として検索や変換を行うならCLOB、内容をバイト列のまま保持するならBLOBを基本候補にします。
多言語文字を各国語文字セットで管理する明確な理由がある場合はNCLOBを検討します。
たとえばPDFや画像は内容を文字列として扱わないため、通常はBLOBが候補になります。
一方、長文の説明や文書本文を検索・編集したい場合は、CLOBとして扱う方が自然です。
LOBをデータベース内に保存するべきケース
行データとファイルを同じトランザクションで管理し、権限、監査、バックアップを一体化したい場合はBLOBやCLOBが向いています。
レコードの削除と添付ファイルの削除を同時に成功または失敗させたい場合は、DB内保存の利点が大きくなります。
バックアップ対象を一本化できる反面、データベース容量や復旧時間が増える点も事前に評価します。
外部ストレージも比較したいケース
巨大ファイルを多数配信し、更新整合性より配信コストや転送性能を優先する場合は、オブジェクトストレージなども比較します。
BFILEは外部ファイルを参照できますが、外部ファイル自体はデータベースのトランザクションに参加しないため、消失や移動への対策が必要です。
配信回数が多く、ファイル本体を更新する機会が少ない用途では、外部保存の方が運用しやすい場合があります。
DBには識別子、保存先、ハッシュ値、サイズなどのメタ情報だけを保持する構成も比較対象になります。
Oracle LOBの仕組みと4種類の違い
LOBは大容量データの本体と、その本体を参照する情報を分けて扱うため、通常の短い文字列列とは操作感が異なります。
ここでは各型の役割だけでなく、アプリケーションから見た扱い方の違いも合わせて確認します。
仕組みを理解すると、NULL、空LOB、ロケータの扱いで起こる混乱を減らせます。
LOBとLOBロケータの関係
LOBロケータはLOB本体を指し示す参照情報であり、アプリケーションやDBMS_LOBはこのロケータを通じて内容を読み書きします。
ロケータだけを長期間保持する設計は避け、取得した接続とトランザクションの範囲で処理を完了させる方が安全です。
ロケータは本体そのものではないため、単純な値として別接続へ渡す設計には注意が必要です。
読み書き処理では、ロケータを取得した接続が有効な間に必要な操作を完了させます。
BLOB・CLOB・NCLOB・BFILEの特徴
BLOBは画像やPDFのようなバイナリを保持し、CLOBはデータベース文字セットの大容量文字を保持します。
NCLOBは各国語文字セットを利用するため、既存の文字コード設計との整合性を確認してから採用します。
BFILEは外部ファイルをDBから参照する型であり、ファイル本体の更新や削除はOS側の管理に依存します。
VARCHAR2とCLOBの使い分け
値が列の上限内に収まり、通常の文字列関数や索引を中心に扱うならVARCHAR2の方が単純です。
将来の増加を含めて大容量になり、部分読み書きやLOB専用APIが必要になるならCLOBを検討します。
現在の最大長だけでなく、数年後の増加や、全文を頻繁に検索するかどうかも判断材料になります。
CLOBを選ぶとLOB専用の読書き処理が必要になるため、小さい文字列へ安易に使うと実装が複雑になります。
LONGからLOBへ移行する理由
LONGは利用できるSQL操作や表設計に制約が多いため、新規設計ではLOBを選ぶのが基本です。
既存表にLONGが残っている場合は、アプリケーション、ビュー、バッチ処理への影響を確認してから移行します。
移行後は、LOB向けの関数やストレージ設定を利用できるため、保守方法を統一しやすくなります。
NULLと空LOBの違い
NULLはLOBロケータ自体がない状態で、EMPTY_BLOBやEMPTY_CLOBは長さゼロのLOBを初期化した状態です。
DBMS_LOBで後から書き込む処理では、空LOBを登録してロケータをRETURNINGで受け取る方法が使えます。
検索条件やアプリ側の判定では、値が存在しない状態と長さゼロの状態を分けて扱います。
登録処理の仕様を決める際は、未登録をNULLにするか、空LOBで初期化するかを統一します。
SecureFilesを前提にしたLOBテーブル設計
新規設計ではSecureFilesを基本候補にしつつ、Oracleのバージョン、表領域、初期化パラメータを確認してからDDLを確定します。
LOB列の設計では、DDLの書き方よりも、どの設定が運用要件に影響するかを理解することが大切です。
設定ごとの利点と負担を把握し、性能と復旧性の両方を満たす構成を目指します。
SecureFilesとBasicFilesの違い
SecureFilesは現在のOracleで推奨されるLOB記憶域で、圧縮、重複排除、暗号化などの機能を利用できる構成があります。
BasicFilesは既存環境に残っていることがあるため、古い表を運用するときは実際のLOBセグメント種別を確認します。
| 比較項目 | SecureFiles | BasicFiles |
|---|---|---|
| 新規利用 | 基本候補 | 既存互換を中心に確認 |
| 高度な機能 | 圧縮、重複排除、暗号化を利用可能な構成がある | 機能が限定的 |
| 表領域 | ASSM管理の表領域が必要 | 既存構成によって異なる |
| 移行 | 再定義や移行手順を計画する | 移行元として残る場合がある |
新規表ではSecureFilesを前提にし、既存表では現在の形式と移行の必要性を確認する流れが分かりやすいです。
機能差だけでなく、表領域、停止時間、追加領域、バックアップ手順も比較して判断します。
LOB列を持つCREATE TABLEの基本形
表には識別子、ファイル名、MIMEタイプ、サイズ、作成日時などのメタ情報とLOB列を分けて持たせます。
LOB記憶域の指定ではSTORE AS SECUREFILEを使い、必要に応じてLOBセグメント名や表領域を明示します。
メタ情報を通常列に分けると、一覧表示や検索でLOB本体を毎回読み込まずに済みます。
LOBセグメント名や格納先を明示しておくと、容量監視や障害調査でも対象を特定しやすくなります。
インライン格納とアウトオブライン格納
小さいLOBを行内に置ける設定は、行と一緒に読む処理のI/Oを減らせる場合があります。
大きいLOBが多い表では、行外格納によって通常列の走査を軽くできる可能性があります。
平均サイズだけでなく、値の分布を確認し、小さいLOBが大半なのか、一部だけ巨大なのかを把握します。
設定変更の効果は、通常列だけを読むSQLとLOB本体を読むSQLの両方で測定します。
CACHE・NOCACHEの選び方
同じLOBを繰り返し読む処理ではCACHEが有効な場合があります。
巨大ファイルを一度だけ順次読む処理ではNOCACHEの方がバッファキャッシュを圧迫しにくくなります。
CACHEを有効にすると再読込が速くなる可能性がありますが、ほかのデータがキャッシュから追い出される場合があります。
NOCACHEは大容量の順次読取りに向くことがありますが、同じLOBを繰り返し読む処理では不利になる可能性があります。
LOGGING・NOLOGGINGの考え方
LOGGINGは復旧に必要なREDOを重視する設定で、通常の本番データでは基本候補になります。
NOLOGGINGは一部の大量処理を軽くできる場合がありますが、障害時に同じ手順で復旧できるとは限りません。
処理時間だけを見てNOLOGGINGを選ぶと、バックアップから復旧した後にデータを再作成できない問題が起こり得ます。
本番適用前に、障害発生時の復旧手順と再投入手順を実際に確認しておきます。
RETENTIONとPCTVERSIONの確認
LOBの旧バージョン管理方式はSecureFilesとBasicFilesで扱いが異なるため、両者の設定名を混同しないことが重要です。
旧バージョンの保持は、長い読取り処理や同時更新の安定性にも関係します。
設定値を変更するときは、UNDOや表領域の使用量と合わせて影響を測定します。
Oracleバージョン・表領域・DB_SECUREFILEの確認
新しいOracleではSecureFilesが標準的ですが、既存DBや互換設定では期待と異なる記憶域になる可能性があります。
作成前にデータベースのバージョン、互換性、DB_SECUREFILE、表領域がASSMかを確認します。
同じDDLでも環境設定によって作成結果が異なる可能性があるため、作成後のデータディクショナリ確認までを手順に含めます。
開発環境と本番環境で設定が違う場合は、移行時に意図しない形式へ変わらないかも確認します。
LOBのCRUDとDBMS_LOB主要操作
LOB操作は関数名を暗記するより、登録、取得、検索、更新、コピーという目的ごとに選ぶ方が理解しやすくなります。
処理の目的とLOBの大きさを先に整理すると、通常SQLとDBMS_LOBのどちらを使うか判断しやすくなります。
ここでは操作ごとの役割を整理し、必要以上に複雑なAPIを選ばない流れを作ります。
INSERTでBLOB・CLOBを登録する
短いCLOB値は通常のINSERTで登録できる場合があります。
大きい値はバインド変数やドライバのLOB APIを使い、SQL文字列へ直接埋め込まない方法を選びます。
バインド変数を使うと、文字列連結によるSQLの肥大化やエスケープ処理の複雑化を避けやすくなります。
登録前にはサイズ上限と形式を検証し、不正なデータをLOB列へ保存しない仕組みを設けます。
EMPTY_BLOB・EMPTY_CLOBとRETURNINGの使い方
最初に空LOBを登録し、RETURNING句でロケータを受け取り、そのロケータへ内容を書き込む方法があります。
この方式は大容量データを段階的に保存するときに使いやすい一方、同じトランザクション内で完了させる必要があります。
空LOBの登録と本体書込みを別トランザクションに分けると、中途半端なレコードが残る可能性があります。
例外が発生した場合はロールバックし、ロケータやストリームを確実に閉じる処理も用意します。
SELECTでLOB全体または一部を取得する
小さい値なら全体取得でも扱えますが、サイズを確認せず巨大LOBをメモリへ展開する設計は危険です。
一覧画面ではLOB本体を取得せず、ID、名称、サイズ、更新日時などのメタ情報だけを返します。
一覧と詳細でSQLを分けると、不要なLOB転送を減らし、画面表示の応答時間を安定させやすくなります。
プレビュー用途では先頭だけを取得し、利用者が必要としたときに全体を読み込む設計も有効です。
UPDATE・追記・コピーを行う
LOB全体を置き換えるなら通常のUPDATEやドライバのバインド処理を使えます。
全体置換は実装が単純ですが、データ量やREDOが大きくなる場合があります。
追記や部分更新を使う場合は、更新位置と長さを誤ると内容を壊すため、境界条件をテストします。
GETLENGTHでLOBサイズを確認する
DBMS_LOB.GETLENGTHはLOBの長さを返し、BLOBとBFILEではバイト、CLOBとNCLOBでは文字を基準に扱います。
アプリのアップロード制限に使う場合は、DBMS_LOBの結果だけでなく、受信前のHTTP制限も設定します。
サイズ情報は、画面表示、ダウンロード可否、バッチ分割数を決めるためにも利用できます。
文字数とバイト数を混同しないよう、アプリ側の表示単位も明確にします。
SUBSTRとINSTRで部分取得・検索を行う
DBMS_LOB.SUBSTRは指定位置から一部を取り出す処理で、プレビューや先頭確認に向いています。
DBMS_LOB.INSTRはLOB内のパターン位置を探せますが、大量行への全文検索用途では負荷を測定する必要があります。
部分取得は確認画面やログ表示に便利ですが、毎回大きな範囲を切り出すと負荷が増えます。
検索条件が複雑または対象件数が多い場合は、専用の検索方式を別途検討します。
READ・WRITE・WRITEAPPENDで分割処理する
DBMS_LOB.READは指定位置から一定量を読み、DBMS_LOB.WRITEは指定位置へ一定量を書き込みます。
末尾へ順番に追加する処理ではDBMS_LOB.WRITEAPPENDを利用できます。
分割単位は固定値をそのまま採用せず、ネットワーク、メモリ、同時実行数を考慮して決めます。
処理途中で失敗した場合に再開するのか、最初からやり直すのかも設計しておきます。
APPENDとCOPYを使い分ける
DBMS_LOB.APPENDは別のLOB全体を末尾へ連結したい場合に向いています。
APPENDは末尾への連結が目的で、COPYはコピー元とコピー先の位置や長さを指定したい場合に向きます。
同じ処理をアプリ側で一度読み出して書き戻すより、DB内で完結できるかを先に検討します。
LOADCLOBFROMFILE・LOADBLOBFROMFILEで外部ファイルを読む
DBMS_LOB.LOADBLOBFROMFILEは外部ファイルのバイト列をBLOBへ読み込む用途で使います。
DBMS_LOB.LOADCLOBFROMFILEは文字セット変換が関係するため、元ファイルの文字コードを明確にします。
外部ファイルの読込みでは、DIRECTORYオブジェクトとOS上の権限の両方が必要です。
処理後は外部ファイルを残すのか削除するのかを決め、二重管理にならないようにします。
大容量LOBを安全に読み書きする実装方法
大容量LOBでは、SQLが動くことより、メモリ、接続、トランザクション、タイムアウトを安定して管理できることが重要です。
本番環境では、一件を処理できることより、同時実行時にも安定することを基準に実装を評価します。
最大サイズと同時実行数を前提にすると、実運用でのメモリ不足や接続枯渇を防ぎやすくなります。
LOBを一括取得すると起こりやすい問題
巨大LOBを一括で文字列やバイト配列へ変換すると、アプリサーバーのメモリ使用量が急増します。
同時ダウンロードが重なると、単体テストでは見えなかったGC停止やプロセス終了が起こる場合があります。
一件では問題がなくても、同時に複数件を処理すると使用メモリが件数分だけ増える可能性があります。
負荷試験では最大サイズのLOBを使い、実運用に近い同時実行数で確認します。
分割読み書きとストリーミングの基本
ストリーミングでは一定量ずつ読み取り、そのままレスポンスや保存先へ渡します。
一つの巨大バッファを作らず、同時実行数を掛け合わせても許容できる単位を選びます。
読取り、変換、送信の各工程で大きな一時データを作らないことが重要です。
途中で接続が切れた場合の中断処理や再試行方法も、ストリーミング設計に含めます。
BLOBのバイト数とCLOBの文字数の違い
BLOBの位置や長さはバイトを基準にし、CLOBとNCLOBは文字を基準に扱うAPIがあります。
マルチバイト文字を含むCLOBで、文字数とエンコード後のバイト数を同じ値として扱わないようにします。
画面に表示する文字数制限と、通信量を抑えるバイト数制限は別の基準として扱います。
文字コード変換が入る処理では、変換前後のサイズが同じとは限らない点にも注意します。
一時LOBの作成・利用・解放
複数工程で組み立てた結果を一時的に保持する場合は、DBMS_LOB.CREATETEMPORARYで一時LOBを作成できます。
不要になった一時LOBはDBMS_LOB.FREETEMPORARYで解放し、例外発生時にも解放処理が通る構造にします。
一時LOBを長く保持すると、一時領域やセッション資源を圧迫する原因になります。
正常終了だけでなく、例外、タイムアウト、キャンセル時にも解放されることを確認します。
LOBロケータとトランザクション境界
更新用ロケータは取得したトランザクション内で使い、コミット後に同じロケータで書き続けないようにします。
ORA-22990が発生した場合は、ロケータ取得、コミット、書込みの順序を確認します。
複数のサービスやジョブをまたいでロケータを渡すのではなく、必要なデータをその場で読み取る方が安全です。
コミット位置を変更した際は、LOB更新処理の順序が崩れていないか回帰テストを行います。
アップロードサイズと処理時間を制限する
アプリでは最大サイズ、許可形式、処理時間、同時実行数を明示的に制限します。
入口で制限すると、データベースへ到達する前に過大なリクエストを拒否できます。
利用者へは上限値と許可形式を明示し、失敗理由が分かるエラーメッセージを返します。
SecureFilesの圧縮・重複排除・暗号化
SecureFilesの高度な機能は便利ですが、容量削減だけでなくCPU負荷、変更頻度、ライセンス条件を含めて判断します。
各機能は常に有効にするのではなく、保存データの特徴と運用上の目的が一致する場合に検討します。
導入判断では、削減できる容量と増えるCPU負荷や管理作業をセットで比較します。
圧縮が効果を出しやすいデータ
未圧縮の文書や繰り返しが多いデータは、LOB圧縮によって容量を減らせる可能性があります。
JPEG、動画、ZIPなど既に圧縮されたファイルは、追加圧縮の効果が小さい場合があります。
導入前には実データの一部で圧縮率と処理時間を測り、想定どおりの効果があるか確認します。
保存容量だけでなく、バックアップ時間や読取りI/Oがどの程度変わるかも比較します。
重複排除が向いている保存パターン
同じ添付ファイルや同一テンプレートが何度も保存される列では、重複排除が効果を出しやすくなります。
ファイル名が違っても内容が同一になる業務では、重複率を計測して効果を見積もります。
更新が頻繁で同一内容が少ないデータでは、追加処理に対して効果が小さい可能性があります。
暗号化を利用する目的と確認事項
LOB暗号化はディスクやバックアップ上のデータ保護に役立ちます。
通信経路の暗号化やアプリのアクセス制御を代替するものではないため、TLS、権限、監査と組み合わせます。
暗号化を有効にする前に、保護対象、鍵の保管、鍵紛失時の対応、バックアップ復旧手順を整理します。
権限を持つ利用者からの不正閲覧を防ぐには、暗号化だけでなくアクセス制御と監査が必要です。
容量削減とCPU負荷のトレードオフ
圧縮や重複排除はストレージとI/Oを減らせる一方、書込み時のCPU負荷を増やす場合があります。
| 機能 | 向いている条件 | 確認したい負荷 |
|---|---|---|
| 圧縮 | 未圧縮で繰り返しが多いLOB | CPU、書込み時間、圧縮率 |
| 重複排除 | 同一LOBが多数保存される | 重複率、登録時間 |
| 暗号化 | 保存データの保護が必要 | CPU、鍵管理、復旧手順 |
読み取り中心か書込み中心かによって、許容できるCPU負荷と応答時間は変わります。
ピーク時間帯の負荷も測定し、平均値だけで導入可否を判断しないようにします。
エディション・オプション・サービス条件の確認
SecureFiles圧縮と重複排除はAdvanced Compression、暗号化はAdvanced Securityに関係する構成があります。
利用できる機能はOracleのバージョン、エディション、クラウドサービス、契約条件で変わるため、導入前に最新のライセンス資料を確認します。
検証環境で機能が使えても、本番契約で同じ条件とは限らないため、利用可否を記録として残します。
クラウドサービスでは提供形態が異なる場合があるため、サービス固有の仕様も確認します。
既存BasicFilesをSecureFilesへ移行する流れ
移行前にLOB容量、停止可能時間、追加領域、REDO、バックアップ時間を確認します。
オンライン再定義など複数の方法があるため、対象表の制約、索引、パーティション、依存オブジェクトを含めて選びます。
移行前後で件数、LOBサイズ、ハッシュ値などを比較し、内容が変わっていないことを確認します。
切替後に問題が起きた場合の戻し方と、旧セグメントを削除する時期も計画します。
LOBのパフォーマンスを改善する判断ポイント
LOBの性能問題は単一設定で解決するとは限らないため、データ特性、SQL、アプリ、ストレージの順に切り分けます。
改善前には、遅い処理がデータベース、ネットワーク、アプリケーションのどこで発生しているかを分けて確認します。
計測結果を基に一つずつ変更し、どの設定が効果を生んだか分かる形で進めます。
小さいLOBと大きいLOBで格納方法を変える
小さいLOBが大半なら行内格納の効果を確認し、大きいLOBが多いなら通常列と本体のI/Oを分ける設計を検討します。
平均値だけではなく、中央値、最大値、サイズ別件数を確認すると実態を捉えやすくなります。
極端に大きいデータだけを別表や外部ストレージへ分ける設計も比較します。
読み取り頻度からCACHE設定を選ぶ
何度も参照する小さめの文書ではCACHEが有効な場合があります。
アクセス回数が多くても一件当たりが非常に大きい場合は、キャッシュ効率が悪くなる可能性があります。
キャッシュヒット率だけでなく、他の主要SQLへの影響も同時に確認します。
REDO生成量と復旧要件を両立する
LOB更新が多いとREDOとアーカイブログが増え、保存領域やスタンバイ転送へ影響します。
安易にNOLOGGINGへ変えるのではなく、更新方式、まとめ方、差分更新の可否を見直します。
大量更新では、処理時間、REDO量、アーカイブログ転送、バックアップ負荷をまとめて観測します。
復旧可能性を下げる変更は、性能上の利点が大きくても慎重に判断します。
読み書き単位とチャンクサイズを考える
小さすぎる単位は呼出し回数を増やし、大きすぎる単位はメモリと待ち時間を増やします。
適切な単位はドライバやネットワークにも左右されるため、複数の値で比較します。
処理時間の短縮だけでなく、メモリの最大使用量と失敗時の再処理量も評価します。
LOB列への検索方法とインデックスの考え方
LOB本体へ通常のB-tree索引を付けて全文検索する設計はできません。
文書内容を検索したい場合は、検索要件を整理し、LOB本体を毎回走査しない構成を検討します。
ファイル名、種別、作成者、日付などで絞り込めるよう、メタ情報列へ適切な索引を用意します。
容量・I/O・REDO・一時領域を監視する
LOBセグメント容量だけでなく、LOB索引、表領域の空き、読書きI/O、REDO、一時LOB使用量を監視します。
増加傾向を定期的に記録すると、上限へ到達する前に拡張や削除を計画できます。
通常時の基準値を持っておくと、障害時にどの指標が急変したか判断しやすくなります。
設定変更前後の性能を測定する
変更前に同じデータ量と同じ処理で基準値を取得します。
変更後は処理時間だけでなく、CPU、I/O、REDO、待機イベント、アプリのメモリを比較します。
| 利用ケース | 主な候補 | 重点確認 |
|---|---|---|
| 小さい文書を頻繁に読む | 行内格納とCACHEを検証 | キャッシュ競合 |
| 大きなファイルを一度配信 | 行外格納とNOCACHEを検証 | 順次I/Oと転送 |
| 大量ファイルを一括登録 | 分割書込みとバッチ化を検証 | REDO、CPU、再実行 |
| 同一ファイルが多い | 重複排除を検証 | 重複率と契約条件 |
測定条件を揃えないと、データ量やキャッシュ状態の違いを設定効果と誤認する可能性があります。
改善しなかった場合に元へ戻せるよう、変更内容と測定結果を記録します。
Java・Python・RailsからLOBを扱う
アプリケーション側では、LOB全体を無条件に文字列やバイト配列へ変換しないことが共通の基本です。
使用言語が変わっても、大容量データを一括で保持しないという基本方針は共通します。
フレームワークの便利な自動変換が、大容量時には負荷になる点にも注意します。
アプリケーション共通のストリーミング原則
取得前にサイズを確認し、接続を開いたまま一定量ずつ読み、処理後にストリームと接続を確実に閉じます。
ストリームを返すAPIでは、レスポンス完了までDB接続を保持する設計になっていないか確認します。
接続占有が長くなる場合は、一時ファイルや別ストレージを介する方式も比較します。
Java JDBCでBLOB・CLOBを読み書きする
JavaではBLOBにgetBinaryStream、CLOBにgetCharacterStreamを使うと順次読取りができます。
書込みではsetBinaryStreamやsetCharacterStreamを使い、PreparedStatementのバインド値として渡します。
ストリームの閉じ忘れを防ぐため、例外が発生しても確実に解放される構造で実装します。
ドライバのバージョンによって動作や最適なAPIが異なる場合があるため、利用環境で検証します。
Python oracledbでLOBを扱う
python-oracledbでは通常、BLOBやCLOBをLOBオブジェクトとして受け取り、readやwriteで処理できます。
全体をbytesやstrとして取得する設定もありますが、大容量データではメモリ使用量を確認します。
小さいLOBと大きいLOBで同じ取得方法を使わず、サイズに応じて処理を分けると安定しやすくなります。
非同期処理や並列処理を使う場合は、接続数と同時メモリ使用量を合わせて制御します。
Rails ActiveRecordで扱う際の注意点
Railsでは利用するOracleアダプタとドライバの対応状況を確認し、CLOBやBLOBの型変換をテストします。
モデルから属性へアクセスしただけでLOB全体が読み込まれないか、実際のSQLとメモリ使用量を確認します。
一覧取得ではLOB列を除外し、必要な画面だけで明示的に取得する構成が安全です。
ファイルアップロードAPIの実装フロー
API入口で形式とサイズを検証し、メタ情報を登録してからLOB本体をストリームで保存します。
保存成功と行更新を同じトランザクションで管理し、失敗時は中途半端な行や一時ファイルを残さないようにします。
保存前にウイルス検査や形式検証が必要な場合は、処理順と一時保存場所を決めておきます。
DB登録と本体保存のどちらかだけが成功しないよう、失敗時の後片付けを設計します。
アプリ側で設けたいサイズ・時間・形式の制限
最大ファイルサイズ、許可するMIMEタイプ、拡張子、処理時間、同時実行数を設定します。
制限値は画面、API、リバースプロキシ、アプリ、DBの各層で矛盾しないようにします。
監視では拒否件数やタイムアウト件数を記録し、利用実態に応じて見直します。
LOBで起こりやすいエラーと性能問題の直し方
障害時はエラー文だけで設定を変えず、再現条件と処理順を確認して原因を絞り込みます。
再現条件、対象データの大きさ、接続とコミットの順序を記録すると、原因の切り分けが進めやすくなります。
症状ごとに確認順を決めておくと、場当たり的な設定変更を避けられます。
ORA-22285とDIRECTORY設定を確認する
ORA-22285では、Oracle DIRECTORYオブジェクト、OS上のパス、ファイル名、権限を順に確認します。
データベースサーバーから見えるパスであることを確認し、アプリサーバーのローカルパスと混同しないようにします。
ファイル名の大文字小文字や、実行ユーザーから見た権限も確認対象になります。
環境ごとにパスが異なる場合は、設定値として管理し、SQLへ固定値を書かないようにします。
ORA-22990とトランザクション管理を見直す
ORA-22990では、LOBロケータを取得した後にコミットし、そのロケータで更新を続けていないか確認します。
ロケータの取得から書込みまでを同じ接続とトランザクションへまとめます。
フレームワークが自動コミットしている場合は、意図しないタイミングで境界が切れていないか確認します。
再現テストでは接続プールを利用した状態も含め、同じ接続が維持されているかを追跡します。
ORA-01555と長時間処理を切り分ける
長時間のLOB読取り中にORA-01555が出る場合は、処理時間、同時更新、UNDO保持、コミット方式を確認します。
単純にUNDOを増やす前に、対象範囲を分割できるか、不要な長時間参照を減らせるかを検討します。
処理対象を小さな単位へ分けると、同じスナップショットを長時間保持する必要を減らせます。
更新の多い時間帯を避ける運用変更で改善するかも確認します。
メモリ不足が起きたときの確認順
まずLOB全体をtoStringやbytesへ変換していないかを確認します。
次に同時実行数、バッファサイズ、フレームワークの自動変換、レスポンスの一時保持を確認します。
一件当たりの使用量だけでなく、同時実行数を掛けた最大値を見積もります。
アプリのヒープだけでなく、ネイティブバッファや一時ファイルの使用量も確認します。
LOBの書き込みが遅いときの確認順
書込み単位、ネットワーク往復、コミット回数、索引、トリガー、圧縮、暗号化、REDO待機を順に確認します。
アプリとDB間の往復が多い場合は、書込み単位を大きくすることで改善する可能性があります。
ただし単位を大きくしすぎるとメモリや再試行コストが増えるため、実測で決めます。
REDOやバックアップが肥大化した場合の対策
LOB更新量と更新方式を確認し、全体置換を差分更新へ変えられるか検討します。
保持期限を過ぎたLOBの削除、パーティション化、アーカイブ、外部ストレージ移行も候補になります。
更新頻度が低いデータと高いデータを分けると、バックアップや保管方針を変えやすくなります。
削除済みデータの領域がすぐに返却されるとは限らないため、セグメントの状態も確認します。
設計・実装・運用前の最終チェックリスト
LOB設計は型を決めて終わりではなく、保存、読書き、復旧、監視まで一続きで確認することが重要です。
チェック項目を設計書やレビュー項目として残すと、担当者が変わっても同じ基準で確認できます。
実装前と本番投入前の二段階で確認し、抜け漏れを減らします。
型選定で確認する項目
文字かバイナリか、文字コードは何か、データベース内で更新するかを確認します。
将来の最大サイズ、検索方法、更新頻度、アプリ側のAPIまで含めて記録します。
判断理由を残すことで、後から要件が変わった際に見直しやすくなります。
DB内保存と外部保存を比較する項目
トランザクション、アクセス制御、バックアップを一体化したいならDB内保存が有力です。
配信性能、保管費用、バックアップ、アクセス制御、削除整合性を同じ表で比較します。
初期構築の簡単さだけでなく、数年分のデータが蓄積した後の運用も想定します。
SecureFiles設定で確認する項目
Oracleバージョン、DB_SECUREFILE、ASSM表領域、行内格納、CACHE、LOGGINGを確認します。
圧縮、重複排除、暗号化を使う場合は、効果測定と利用条件の確認も項目へ追加します。
作成後は実際のLOBセグメント種別と設定値を確認し、DDLの想定と一致しているか確かめます。
読み書き処理で確認する項目
一覧取得でLOB本体を読まないこと、巨大LOBを一括展開しないこと、ロケータをトランザクション外へ持ち出さないことを確認します。
正常系だけでなく、途中切断、タイムアウト、再試行、ロールバック時の動作も確認します。
最大サイズのデータを複数同時に処理し、接続数とメモリ使用量が許容範囲か測定します。
バックアップ・復旧・監視で確認する項目
LOBを含むバックアップ時間と復旧時間を測定し、目標時間内に戻せることを確認します。
バックアップが成功するだけでなく、実際にLOBを含めて復旧できることを定期的に試験します。
容量、I/O、REDO、処理時間のしきい値を決め、異常を早期に検知できるようにします。
LOBが向いているケースと向いていないケース
データベースの整合性、権限、監査、バックアップと一体で管理したい文書や添付ファイルにはLOBが向いています。
巨大ファイルを大量配信し、データベースのトランザクション管理が不要な用途では外部ストレージが向く場合があります。
DB内保存を選ぶ場合は、整合性と管理の一体化にどれだけ価値があるかを明確にします。
外部保存を選ぶ場合も、参照切れや削除漏れを防ぐための管理情報と定期確認が必要です。
DB内保存を選ぶ場合は、整合性と管理の一体化にどれだけ価値があるかを明確にします。
外部保存を選ぶ場合も、参照切れや削除漏れを防ぐための管理情報と定期確認が必要です。