【完全ガイド】Oracle LOB(BLOB/CLOB)操作 徹底解説|DBMS_LOB・SecureFiles・暗号化まで
- 作成日 2026.07.27
- Oracle Database
Oracle で大容量データを扱う際の必須スキル、LOB(Large Object):
CREATE TABLE documents (
doc_id NUMBER PRIMARY KEY,
doc_title VARCHAR2(200),
doc_body CLOB, -- 大容量テキスト
doc_image BLOB -- バイナリ画像
) LOB (doc_body, doc_image) STORE AS SECUREFILE;
LOB は最大 128 TBまで格納可能。しかし、通常のカラムと同じ感覚で扱うと問題:
- メモリを圧迫する(大容量を一括ロード)
- REDO ログが肥大化
- バックアップ・リストアに時間
- ネットワーク転送のボトルネック
- アプリ側でストリーミングが必須
DBMS_LOBの理解が必須- SecureFiles vs BasicFilesの選択
- 圧縮・重複排除・暗号化の活用
現場では:
- 画像・PDF・動画の格納
- JSON/XML の大容量ドキュメント
- ログデータ・監査データ
- メールアーカイブ
- 文書管理システム
- Web アプリのファイルアップロード
- AI・機械学習モデルの保存
さらに、Oracle 11g で導入された SecureFiles は BasicFiles を完全に置き換えるものですが、日本語圏で体系的な解説がほぼないのが現状:
- SecureFiles と BasicFiles の違いを知らない
- DBMS_LOB.LOADCLOBFROMFILE の使い方
- 一時 LOB(Temporary LOB) の存在
- CACHE vs NOCACHE の判断
- INLINE vs OUT OF ROW の設計
- Rails/Java/Python でのストリーミング
- Oracle Text による全文検索
本記事では、Oracle LOB(BLOB/CLOB)操作の完全ガイドを、リファレンスとして実用的に整理します。4種類の LOB 型、テーブル作成、CRUD 操作、DBMS_LOB パッケージ、SecureFiles、圧縮・暗号化、パフォーマンスチューニング、Rails/Java/Python 対応、Oracle Text、実践シナリオ、FAQまで完全網羅。この1本で Oracle LOB を根本から使いこなせるようになります。
結論:BLOB / CLOB の使い分け
時間がない方向けに、最速の理解を示します。
4種類の LOB
| 型 | 用途 | 例 |
|---|---|---|
| BLOB | バイナリ | 画像、PDF、動画 |
| CLOB | 文字(DB キャラセット) | 大容量テキスト、JSON、XML |
| NCLOB | Unicode 文字 | 多言語テキスト |
| BFILE | 外部ファイル参照 | 外部ストレージ |
最小限のセットアップ
-- ✅ 現代的(SecureFiles)
CREATE TABLE docs (
id NUMBER PRIMARY KEY,
body CLOB
) LOB (body) STORE AS SECUREFILE (
ENABLE STORAGE IN ROW -- 小さいものはインライン
COMPRESS HIGH -- 圧縮
DEDUPLICATE -- 重複排除
);
5大操作
-- ① INSERT
INSERT INTO docs (id, body) VALUES (1, 'text content...');
-- ② SELECT
SELECT body FROM docs WHERE id = 1;
-- ③ UPDATE
UPDATE docs SET body = 'new content' WHERE id = 1;
-- ④ サイズ取得
SELECT DBMS_LOB.GETLENGTH(body) FROM docs;
-- ⑤ 部分読み取り
SELECT DBMS_LOB.SUBSTR(body, 100, 1) FROM docs;
覚えるべき 3 つのポイント
1. LOB は SecureFiles で作成(11g 以降推奨)
2. 大容量は DBMS_LOB でストリーミング
3. アプリ側で少しずつ読み書き(メモリ節約)
詳細は以下で解説します。
まず理解する:LOB の全体像
LOB とは
Large Object の略、大容量データを格納する型:
- 最大 128 TB(DB ブロックサイズ 32K 時)
- テーブル外に格納(デフォルト)
- ロケータ(LOB Locator) で参照
- 専用 API(DBMS_LOB)で操作
従来型との違い
| 型 | 最大サイズ | 特徴 |
|---|---|---|
| VARCHAR2 | 4000 バイト(32K で拡張可) | 通常の文字列 |
| RAW | 2000 バイト | バイナリ小 |
| LONG | 2 GB | 非推奨 |
| LONG RAW | 2 GB | 非推奨 |
| CLOB | 128 TB | 推奨(文字) |
| BLOB | 128 TB | 推奨(バイナリ) |
LONG は非推奨
-- ❌ LONG(Oracle 8i 以前の旧型)
CREATE TABLE t (col LONG);
-- 制限多数、LOB への移行推奨
-- ✅ CLOB / BLOB
CREATE TABLE t (col CLOB);
LONG の制限:
- テーブルあたり1つのみ
- SUBSTR できない
- インデックス不可
- 分散処理不可
LOB Locator
LOB の実データは別領域、テーブルの列には**ロケータ(参照)**のみ:
[テーブル行]
├─ id: 1
├─ title: '...'
└─ body_lob: [ロケータ] → 実データ(LOB セグメント)
行のサイズを抑えるため。
4種類の LOB 詳細
BLOB(バイナリ)
CREATE TABLE files (
file_id NUMBER PRIMARY KEY,
content BLOB
);
用途:
- 画像(JPEG, PNG, GIF)
- PDF、Excel、Word
- 動画、音声
- ZIP アーカイブ
- 暗号化データ
CLOB(文字)
CREATE TABLE articles (
article_id NUMBER PRIMARY KEY,
body CLOB -- DB キャラセット
);
用途:
- 記事本文
- JSON ドキュメント
- XML
- ソースコード
- ログテキスト
NCLOB(Unicode 文字)
CREATE TABLE i18n_docs (
doc_id NUMBER PRIMARY KEY,
content NCLOB -- 国際キャラセット(AL16UTF16 等)
);
用途:
- 多言語テキスト
- CJK(中国・日本・韓国)
- 絵文字対応
注意: DB キャラセットが AL32UTF8 なら CLOB で十分。
BFILE(外部ファイル)
-- ディレクトリ登録
CREATE DIRECTORY doc_dir AS '/u01/documents';
CREATE TABLE ext_files (
file_id NUMBER PRIMARY KEY,
ext_ref BFILE
);
INSERT INTO ext_files
VALUES (1, BFILENAME('DOC_DIR', 'sample.pdf'));
特徴:
- 参照のみ(DB 内に格納しない)
- 読み取り専用
- バックアップ・レプリケーション対象外
用途: 大容量ファイル、外部連携。ディレクトリ設定の詳細は Oracle Directory 確認の記事も参照してください。
テーブル作成の詳細
基本形(BasicFiles)
-- 古い形式(BasicFiles)
CREATE TABLE t (id NUMBER, body CLOB);
Oracle 11g+ でもデフォルトは BasicFiles。SecureFiles を明示的に指定推奨。
SecureFiles(推奨)
CREATE TABLE t (
id NUMBER PRIMARY KEY,
body CLOB
) LOB (body) STORE AS SECUREFILE (
ENABLE STORAGE IN ROW -- インライン化
CHUNK 8192 -- 8K チャンク
RETENTION AUTO -- 自動保持
CACHE -- バッファキャッシュ利用
COMPRESS HIGH -- 圧縮(Advanced Compression 必要)
DEDUPLICATE -- 重複排除
ENCRYPT -- 暗号化(TDE 必要)
);
主要オプション
STORAGE:
ENABLE STORAGE IN ROW -- 3964 バイト以下はインライン
DISABLE STORAGE IN ROW -- 常にアウトオブライン
CHUNK:
CHUNK 8192 -- LOB の物理単位(DB ブロックサイズの倍数)
LOGGING:
LOGGING -- REDO 記録(デフォルト)
NOLOGGING -- REDO なし(高速だが復旧不可)
FILESYSTEM_LIKE_LOGGING -- SecureFiles 専用、メタデータのみ
CACHE:
CACHE -- バッファキャッシュ利用(頻繁アクセス)
NOCACHE -- 直接読み書き(大容量、一回限り)
CACHE READS -- 読み取りのみキャッシュ
基本 CRUD 操作
INSERT
方法A: リテラル(4000 バイト以下):
INSERT INTO docs (id, body)
VALUES (1, 'Small text content');
方法B: EMPTY_CLOB / EMPTY_BLOB:
-- 空の LOB を作成、後で書き込み
INSERT INTO docs (id, body)
VALUES (1, EMPTY_CLOB())
RETURNING body INTO :lob_locator;
-- ロケータで書き込み
DBMS_LOB.WRITE(:lob_locator, ...);
方法C: PL/SQL 変数:
DECLARE
v_body CLOB := 'Long text content...';
BEGIN
INSERT INTO docs (id, body) VALUES (1, v_body);
END;
/
SELECT
方法A: 直接(メモリ許容範囲):
SELECT body FROM docs WHERE id = 1;
-- 全内容をロード
方法B: DBMS_LOB で部分読み取り:
DECLARE
v_lob CLOB;
v_chunk VARCHAR2(4000);
v_offset INTEGER := 1;
BEGIN
SELECT body INTO v_lob FROM docs WHERE id = 1;
v_chunk := DBMS_LOB.SUBSTR(v_lob, 4000, v_offset);
-- 4000 バイトずつ処理
END;
/
UPDATE
-- 全置換
UPDATE docs SET body = 'new content' WHERE id = 1;
-- 部分更新(DBMS_LOB)
DECLARE
v_lob CLOB;
BEGIN
SELECT body INTO v_lob FROM docs WHERE id = 1 FOR UPDATE;
DBMS_LOB.APPEND(v_lob, ' additional text');
COMMIT;
END;
/
DELETE
DELETE FROM docs WHERE id = 1;
-- LOB データも自動削除
DBMS_LOB パッケージ主要関数
GETLENGTH
LOB のサイズ取得:
SELECT DBMS_LOB.GETLENGTH(body) FROM docs WHERE id = 1;
-- CLOB: 文字数、BLOB: バイト数
SUBSTR
部分抽出:
SELECT DBMS_LOB.SUBSTR(body, 100, 1) FROM docs WHERE id = 1;
-- 位置1から100文字
INSTR
文字列検索:
SELECT DBMS_LOB.INSTR(body, 'error') FROM docs WHERE id = 1;
-- 'error' の位置
APPEND
追記:
DBMS_LOB.APPEND(dst_lob, src_lob);
COPY
LOB 間コピー:
DBMS_LOB.COPY(dst, src, amount, dst_offset, src_offset);
READ / WRITE
バッファ経由:
DECLARE
v_lob CLOB;
v_buffer VARCHAR2(4000);
v_amount INTEGER := 4000;
v_offset INTEGER := 1;
BEGIN
SELECT body INTO v_lob FROM docs WHERE id = 1;
LOOP
DBMS_LOB.READ(v_lob, v_amount, v_offset, v_buffer);
-- v_buffer を処理
v_offset := v_offset + v_amount;
EXIT WHEN v_amount < 4000;
END LOOP;
END;
/
LOADCLOBFROMFILE / LOADBLOBFROMFILE
ファイルから LOB へ読み込み:
DECLARE
v_bfile BFILE := BFILENAME('DOC_DIR', 'document.pdf');
v_blob BLOB;
v_dest_offset INTEGER := 1;
v_src_offset INTEGER := 1;
BEGIN
INSERT INTO docs (id, doc_binary)
VALUES (1, EMPTY_BLOB())
RETURNING doc_binary INTO v_blob;
DBMS_LOB.OPEN(v_bfile, DBMS_LOB.LOB_READONLY);
DBMS_LOB.LOADBLOBFROMFILE(
dest_lob => v_blob,
src_bfile => v_bfile,
amount => DBMS_LOB.GETLENGTH(v_bfile),
dest_offset => v_dest_offset,
src_offset => v_src_offset
);
DBMS_LOB.CLOSE(v_bfile);
COMMIT;
END;
/
CLOB 版:
DBMS_LOB.LOADCLOBFROMFILE(
dest_lob => v_clob,
src_bfile => v_bfile,
amount => DBMS_LOB.LOBMAXSIZE,
dest_offset => v_dest_offset,
src_offset => v_src_offset,
bfile_csid => 0,
lang_context => 0,
warning => v_warning
);
一時 LOB(Temporary LOB)
PL/SQL 内で一時的に使う:
DECLARE
v_temp CLOB;
BEGIN
DBMS_LOB.CREATETEMPORARY(v_temp, TRUE); -- session キャッシュ
DBMS_LOB.WRITEAPPEND(v_temp, 5, 'Hello');
DBMS_LOB.WRITEAPPEND(v_temp, 6, ' World');
-- 使用
INSERT INTO docs (id, body) VALUES (1, v_temp);
DBMS_LOB.FREETEMPORARY(v_temp); -- 明示的に解放
END;
/
用途:
- アセンブル: 少しずつ組み立て
- 中間処理: 加工用
- メモリ効率: 大量データの分割処理
Oracle 21c+ では自動解放もあるが、明示的解放が安全。
SecureFiles vs BasicFiles
完全比較
| 項目 | BasicFiles | SecureFiles |
|---|---|---|
| 導入 | Oracle 8i | Oracle 11g |
| パフォーマンス | 標準 | 高速 |
| 圧縮 | 不可 | 可能(要ライセンス) |
| 重複排除 | 不可 | 可能(要ライセンス) |
| 暗号化 | 不可 | 可能(TDE) |
| ロギング | LOGGING/NOLOGGING | + FILESYSTEM_LIKE_LOGGING |
| 推奨 | ❌ | ✅ |
SecureFiles 有効化(DB レベル)
-- パラメータ設定
ALTER SYSTEM SET db_securefile = 'PREFERRED' SCOPE = BOTH;
-- ALWAYS: 常に SecureFiles
-- PREFERRED: SecureFiles 優先
-- PERMITTED: 明示指定時のみ
-- FORCE: SecureFiles 強制
パラメータ確認は Oracle パラメータ確認(V$PARAMETER)の記事も参照してください。
既存 BasicFiles の移行
-- オンライン変換(12c+)
ALTER TABLE t MOVE LOB(body) STORE AS SECUREFILE (
CACHE COMPRESS HIGH DEDUPLICATE
);
圧縮・重複排除・暗号化
圧縮
CREATE TABLE t (
id NUMBER, body CLOB
) LOB (body) STORE AS SECUREFILE (COMPRESS HIGH);
レベル:
- NOCOMPRESS: 圧縮なし(デフォルト)
- COMPRESS LOW: 軽量
- COMPRESS MEDIUM: 標準
- COMPRESS HIGH: 高圧縮
トレードオフ: ストレージ削減 vs CPU 使用。
Advanced Compression オプション必要。
重複排除
CREATE TABLE t (
id NUMBER, body CLOB
) LOB (body) STORE AS SECUREFILE (DEDUPLICATE);
同じ内容の LOB は1つだけ格納、参照カウント方式。
用途:
- メール本文(同じ本文の複数受信者)
- テンプレート
- 添付ファイル
暗号化
CREATE TABLE t (
id NUMBER, body CLOB
) LOB (body) STORE AS SECUREFILE (ENCRYPT USING 'AES256');
TDE(Transparent Data Encryption) 必要:
- ウォレット設定
- キー管理
パフォーマンスチューニング
INLINE vs OUT OF ROW
-- インライン(3964 バイト以下)
ENABLE STORAGE IN ROW -- 推奨(小規模 LOB)
-- アウトオブライン
DISABLE STORAGE IN ROW -- 常に別領域
推奨: ENABLE STORAGE IN ROW(デフォルト)。
CACHE 設定
CACHE -- バッファキャッシュ使用
NOCACHE -- 使用しない(大容量)
CACHE READS -- 読み取りのみ
基準:
- 頻繁アクセス: CACHE
- 一度限り: NOCACHE
LOGGING
LOGGING -- REDO 記録(デフォルト)
NOLOGGING -- REDO なし
FILESYSTEM_LIKE_LOGGING -- SecureFiles、メタデータのみ
用途:
- 本番: LOGGING(復旧のため)
- 一時テーブル: NOLOGGING(高速)
CHUNK サイズ
CHUNK 8192 -- 8K
CHUNK 32768 -- 32K(大容量向け)
DB ブロックサイズの倍数、大きいほど大容量向き。
インデックス
通常 B-Tree インデックス不可。Oracle Text(全文検索)を使う:
CREATE INDEX doc_body_idx ON docs(body)
INDEXTYPE IS CTXSYS.CONTEXT;
-- 検索
SELECT * FROM docs WHERE CONTAINS(body, 'Oracle') > 0;
Oracle Text は Oracle の全文検索エンジン。
Rails / Java / Python 対応
Rails ActiveRecord
# マイグレーション
class CreateDocs < ActiveRecord::Migration[8.0]
def change
create_table :docs do |t|
t.text :body, limit: 4.gigabytes # CLOB
t.binary :image, limit: 4.gigabytes # BLOB
end
end
end
# 使用
doc = Doc.new
doc.body = "Long text content..."
doc.image = File.binread("image.jpg")
doc.save
# 読み取り(ストリーミング)
Doc.find(1).image # 全量ロード
oracle_enhanced adapter:
text→ CLOBbinary→ BLOB- ストリーミング API 提供
Rails 8 系の詳細は Rails 8 アップグレードガイドの記事、rails db:migrate 使い方の記事、Solid Queue 使い方の記事も参照してください。
Java (JDBC)
// CLOB 書き込み(ストリーミング)
PreparedStatement ps = conn.prepareStatement(
"INSERT INTO docs (id, body) VALUES (?, ?)"
);
ps.setInt(1, 1);
try (Reader reader = new FileReader("large.txt")) {
ps.setCharacterStream(2, reader);
ps.executeUpdate();
}
// BLOB 書き込み
try (InputStream is = new FileInputStream("image.jpg")) {
ps.setBinaryStream(2, is);
ps.executeUpdate();
}
// CLOB 読み取り(ストリーミング)
ResultSet rs = ...;
Clob clob = rs.getClob("body");
try (Reader reader = clob.getCharacterStream()) {
char[] buf = new char[4096];
int read;
while ((read = reader.read(buf)) != -1) {
// 処理
}
}
Python (oracledb)
import oracledb
# CLOB 書き込み
cursor.execute("""
INSERT INTO docs (id, body) VALUES (:id, :body)
""", id=1, body="Long text content...")
# 大容量ファイル書き込み
with open("large.txt", "rb") as f:
content = f.read()
cursor.execute("""
INSERT INTO docs (id, body_blob) VALUES (:id, :body)
""", id=1, body=content)
# ストリーミング読み取り
cursor.execute("SELECT body FROM docs WHERE id = 1")
lob, = cursor.fetchone()
# 少しずつ読み取り
chunk_size = 65536
offset = 1
while True:
chunk = lob.read(offset, chunk_size)
if not chunk:
break
# 処理
offset += chunk_size
実践シナリオ
シナリオ1:ファイルアップロード API
-- テーブル設計
CREATE TABLE uploads (
upload_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
file_name VARCHAR2(255) NOT NULL,
mime_type VARCHAR2(100),
file_size NUMBER,
content BLOB
) LOB (content) STORE AS SECUREFILE (
ENABLE STORAGE IN ROW
COMPRESS MEDIUM
CACHE READS
);
-- CHECK 制約:ファイルサイズ上限
ALTER TABLE uploads ADD CONSTRAINT chk_size
CHECK (file_size < 10485760); -- 10 MB
制約エラーは ORA-01400: NOT NULL の記事も参照してください。
シナリオ2:文書管理システム
CREATE TABLE documents (
doc_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
title VARCHAR2(500),
author_id NUMBER,
content CLOB,
metadata CLOB, -- JSON
created_at TIMESTAMP DEFAULT SYSTIMESTAMP
) LOB (content, metadata) STORE AS SECUREFILE (
COMPRESS HIGH
DEDUPLICATE
);
-- 全文検索
CREATE INDEX doc_content_idx ON documents(content)
INDEXTYPE IS CTXSYS.CONTEXT;
-- 検索
SELECT title
FROM documents
WHERE CONTAINS(content, 'Oracle AND SecureFile') > 0;
シナリオ3:メールアーカイブ
CREATE TABLE emails (
email_id NUMBER PRIMARY KEY,
from_addr VARCHAR2(255),
to_addr VARCHAR2(255),
subject VARCHAR2(500),
body CLOB,
attachments BLOB
) LOB (body, attachments) STORE AS SECUREFILE (
COMPRESS HIGH
DEDUPLICATE -- 同じメール本文で削減
);
シナリオ4:ログデータ格納
CREATE TABLE app_logs (
log_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
log_time TIMESTAMP DEFAULT SYSTIMESTAMP,
log_level VARCHAR2(10),
message CLOB
) LOB (message) STORE AS SECUREFILE (
NOCACHE -- 書き込みメイン
FILESYSTEM_LIKE_LOGGING -- REDO 軽減
COMPRESS LOW
);
-- パーティション(月次)
PARTITION BY RANGE (log_time)
INTERVAL (NUMTOYMINTERVAL(1, 'MONTH'))
(...);
パーティション関連は Oracle Tablespace 管理の記事も参照してください。
シナリオ5:Rails でのファイルアップロード
# app/models/document.rb
class Document < ApplicationRecord
# body: CLOB
# attachment: BLOB
validates :title, presence: true
validate :attachment_size
private
def attachment_size
if attachment.present? && attachment.bytesize > 10.megabytes
errors.add(:attachment, "too large")
end
end
end
# app/controllers/documents_controller.rb
def create
doc = Document.new(document_params)
if params[:file].present?
doc.attachment = params[:file].read
end
doc.save
end
シナリオ6:Java Spring からのストリーミング
@RestController
public class FileController {
@PostMapping("/upload")
public ResponseEntity<Void> upload(@RequestParam("file") MultipartFile file)
throws SQLException, IOException {
try (PreparedStatement ps = conn.prepareStatement(
"INSERT INTO uploads (file_name, content) VALUES (?, ?)"
)) {
ps.setString(1, file.getOriginalFilename());
ps.setBinaryStream(2, file.getInputStream(), file.getSize());
ps.executeUpdate();
}
return ResponseEntity.ok().build();
}
@GetMapping("/download/{id}")
public void download(@PathVariable Long id, HttpServletResponse response)
throws SQLException, IOException {
try (PreparedStatement ps = conn.prepareStatement(
"SELECT content FROM uploads WHERE upload_id = ?"
)) {
ps.setLong(1, id);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
Blob blob = rs.getBlob("content");
try (InputStream is = blob.getBinaryStream()) {
is.transferTo(response.getOutputStream());
}
}
}
}
}
}
シナリオ7:Data Pump インポート
# LOB を含むテーブルの exp/imp
expdp system/pw tables=docs directory=DP_DIR dumpfile=docs.dmp
impdp system/pw tables=docs directory=DP_DIR dumpfile=docs.dmp
Data Pump の詳細は Oracle Data Pump 使い方の記事も参照してください。
シナリオ8:Docker Oracle での確認
docker exec -it oracle-xe sqlplus scott/tiger <<EOF
CREATE TABLE test_lob (
id NUMBER, body CLOB
) LOB (body) STORE AS SECUREFILE;
INSERT INTO test_lob VALUES (1, 'Test content');
SELECT DBMS_LOB.GETLENGTH(body) FROM test_lob;
EOF
Docker 関連は docker daemon 接続エラーの記事、Docker no space left on device の記事も参照してください。
シナリオ9:Autonomous DB での LOB
Autonomous DB はデフォルトで SecureFiles、追加設定不要。圧縮・暗号化は自動。
シナリオ10:LOB のマイグレーション
-- BasicFiles → SecureFiles
ALTER TABLE t MOVE LOB(body) STORE AS SECUREFILE (
CACHE
COMPRESS HIGH
DEDUPLICATE
);
-- インデックス再構築
ALTER INDEX doc_content_idx REBUILD;
予防のベストプラクティス
1. SecureFiles を使う
STORE AS SECUREFILE -- 常に指定
2. 適切なストレージオプション
ENABLE STORAGE IN ROW -- 小規模含む
CHUNK 8192 -- 適切なチャンクサイズ
3. 圧縮の検討
COMPRESS MEDIUM -- 大容量テキストで有効
4. 重複排除の活用
DEDUPLICATE -- テンプレート・共通コンテンツ
5. ストリーミングでの読み書き
アプリ側で全量ロードを避ける
少しずつ処理
6. 一時 LOB の解放
DBMS_LOB.FREETEMPORARY(v_temp); -- 必ず解放
7. FILESYSTEM_LIKE_LOGGING
-- ログ・監査で REDO 軽減
FILESYSTEM_LIKE_LOGGING
8. パーティション化
-- 大量 LOB は月次パーティション
PARTITION BY RANGE (created_at) ...
9. アプリでのサイズ制限
CHECK 制約 + アプリバリデーション
10. モニタリング
-- LOB 使用状況
SELECT segment_name, bytes/1024/1024 mb
FROM dba_segments
WHERE segment_type = 'LOBSEGMENT';
トラブルシューティング
ORA-22285: non-existent directory
-- DIRECTORY 未登録
CREATE DIRECTORY doc_dir AS '/u01/documents';
GRANT READ ON DIRECTORY doc_dir TO scott;
Directory 関連は Oracle Directory 確認の記事も参照してください。
ORA-01555: snapshot too old
大容量 LOB での長時間読み取り:
-- UNDO 領域を増やす
ALTER SYSTEM SET undo_retention = 3600;
Snapshot too old は ORA-01555: snapshot too old の記事も参照してください。
ORA-22990: LOB locators cannot span transactions
-- LOB ロケータはトランザクションを跨げない
-- 各トランザクションで再取得
メモリ不足
アプリ側で全量ロード → メモリ枯渇
→ ストリーミング API 使用
遅い書き込み
-- NOLOGGING + APPEND ヒント
INSERT /*+ APPEND */ INTO t ...;
バックアップ肥大化
LOB は行データと別領域 → バックアップ影響大
→ 圧縮・重複排除で軽減
よくある質問(FAQ)
Q1. LONG と LOB の違い
- LONG: 旧型、非推奨
- LOB: モダン、CLOB/BLOB 推奨
Q2. VARCHAR2 と CLOB の使い分け
- VARCHAR2: 4000 バイト以下(拡張で 32K)
- CLOB: それ以上(最大 128 TB)
Q3. SecureFiles か BasicFiles か
SecureFiles 一択(11g 以降推奨)。
Q4. 圧縮のライセンス
Advanced Compression オプション必要(有償)。
Q5. 暗号化のライセンス
Advanced Security(TDE)必要(有償)。
Q6. 全文検索
Oracle Text(CTXSYS)で CONTAINS()。
Q7. Rails での対応
text / binary 型で自動 CLOB/BLOB マッピング。
Q8. LOB のサイズ確認
SELECT DBMS_LOB.GETLENGTH(body) FROM t;
Q9. LOB のインデックス
通常 B-Tree 不可、Oracle Text 使用。
Q10. NULL LOB
IS NULL / IS NOT NULL でチェック可能
Q11. 一時 LOB のセッション有効期間
DBMS_LOB.SESSION 指定でセッション終了時解放。明示的解放推奨。
Q12. Autonomous DB での挙動
自動 SecureFiles、自動圧縮・暗号化。
参考リンク
Oracle 公式
- Oracle Database SecureFiles and Large Objects Developer’s Guide
- DBMS_LOB Package
- SecureFiles LOBs
- Oracle Text Reference
まとめ
Oracle LOB(BLOB/CLOB)操作の要点を再整理します。
4種類の LOB
| 型 | 用途 |
|---|---|
| BLOB | バイナリ(画像、PDF、動画) |
| CLOB | 文字(テキスト、JSON、XML) |
| NCLOB | Unicode(多言語) |
| BFILE | 外部ファイル参照 |
モダンなテーブル設計
CREATE TABLE t (
id NUMBER PRIMARY KEY,
body CLOB
) LOB (body) STORE AS SECUREFILE (
ENABLE STORAGE IN ROW -- 小規模インライン
COMPRESS HIGH -- 圧縮
DEDUPLICATE -- 重複排除
CACHE -- キャッシュ
);
主要 DBMS_LOB 関数
DBMS_LOB.GETLENGTH(lob) -- サイズ
DBMS_LOB.SUBSTR(lob, amt, off) -- 部分抽出
DBMS_LOB.INSTR(lob, pattern) -- 検索
DBMS_LOB.APPEND(dst, src) -- 追記
DBMS_LOB.COPY(dst, src, ...) -- コピー
DBMS_LOB.READ(lob, amt, off, buf) -- 読み取り
DBMS_LOB.WRITE(lob, amt, off, buf)-- 書き込み
DBMS_LOB.LOADCLOBFROMFILE(...) -- ファイル読み込み
DBMS_LOB.LOADBLOBFROMFILE(...) -- ファイル読み込み
DBMS_LOB.CREATETEMPORARY(lob, ...)-- 一時 LOB
DBMS_LOB.FREETEMPORARY(lob) -- 一時 LOB 解放
SecureFiles vs BasicFiles
| 項目 | BasicFiles | SecureFiles |
|---|---|---|
| 導入 | 8i | 11g |
| 圧縮 | ❌ | ✅ |
| 重複排除 | ❌ | ✅ |
| 暗号化 | ❌ | ✅ |
| 推奨 | ❌ | ✅ |
パフォーマンス
INLINE (< 3964 bytes) → 高速
COMPRESS → ストレージ削減
DEDUPLICATE → 重複コンテンツで大幅削減
CACHE → 頻繁アクセス向け
NOCACHE → 一度限り、大容量
アプリからの操作
Rails: t.text / t.binary
Java: setCharacterStream / setBinaryStream (JDBC)
Python: oracledb で datetime.now() 相当
共通: ストリーミング推奨(メモリ節約)
これらの知識は、Oracle でのファイルアップロード・文書管理・メールアーカイブ・ログシステム・画像/動画配信・全文検索・Rails / Java / Python 開発など、あらゆる場面で活用できます。本記事をブックマークしておけば、Oracle LOB を確実に使いこなせるようになります。
本記事は2026年6月時点の情報をもとに、Oracle Database 19c〜23ai での動作確認・公式ドキュメントに基づき作成しています。Oracle のバージョンにより挙動が異なる場合があるため、最新の情報は Oracle 公式ドキュメント(docs.oracle.com)もあわせてご確認ください。
-
前の記事
【完全ガイド】Oracle 分析関数 (OVER/PARTITION BY) 徹底解説|LEAD・LAG・累計・移動平均・ランキングまで 2026.07.26
-
次の記事
【完全ガイド】Oracle DATE vs TIMESTAMP 違い|精度・タイムゾーン・INTERVAL 徹底解説 2026.07.27
コメントを書く