3 JSONデータの格納および管理の概要
この概要では、(1) JSON列のデータ型、(2) JSONデータ向けのLOB記憶域の考慮事項、(3) JSON列に整形式のJSONデータが格納されていることの確認、について説明します。
JSON列のデータ型
Oracle DatabaseにJSONデータを格納するには、データ型がJSON
、VARCHAR2
、CLOB
またはBLOB
の列を使用します。どのデータ型を使用しても、それらのデータ型の他のデータを操作する場合と同様に、JSONデータを操作できます。標準のデータ型を使用してJSONデータを格納すると、アドバンスト・レプリケーションなどのOracle Databaseのすべての機能で、JSON文書が格納された表を使用できるようになります。
ネイティブなバイナリ形式でJSONデータを格納するJSON
データ型を使用することをお薦めします。
他のいずれかの型を使用する場合、どれを使用するかは、一般的に、管理が必要なJSON文書のサイズによって決まります。
-
最も大きいJSON文書が4000バイト(または文字)を超えないことが確かな場合は、
VARCHAR2(4000)
を使用します脚注1脚注1。Oracle Exadataを使用している場合は、
VARCHAR2(4000)
を選択すると、パフォーマンスの向上のために一部のJSON操作の実行をExadataの記憶域セルに押し下げることができるため、パフォーマンスを向上させることができます。 -
JSON文書のうち、いくつかが4000バイト(または文字)を超えるということがわかっており、すべて32767バイト(または文字)以下であることが確かな場合は、
VARCHAR2(32767)
を使用します脚注1。VARCHAR2(32767)
の場合、文書の最初の約3.5Kバイト(または文字)は、表の行の一部として表内に格納されます。これは、VARCHAR2(4000)
ではなくVARCHAR2(32767)
を使用することで増えるコストが、約3.5Kより大きい文書にのみ適用されることを意味します。ほとんどの文書がこのサイズよりも小さい場合は、VARCHAR2(4000)
を使用する場合と比べてパフォーマンスにほとんど差は出ません。Oracle Exadataを使用する場合は、行内に格納されているすべての文書に対してプッシュダウンが有効になります。
-
32767バイト(または文字)よりも大きいJSON文書があることがわかっている場合は、
BLOB
(バイナリ・ラージ・オブジェクト)またはCLOB
(キャラクタ・ラージ・オブジェクト)の記憶域を使用します脚注1。
JSON列に整形式のJSONデータが格納されていることの確認
JSON
データ型を使用してJSONデータを格納する場合(推奨)、データは整形式のJSONデータであることが保証されます。それ以外の場合は格納できません。
JSON
データ型を使用してJSONデータを格納しない場合は、SQL/JSON条件is json
を使用して、一部のJSONデータが整形式かどうかを確認できます。この場合、整形式のJSONデータ以外のデータが一部の行に含まれることが予期される場合を除いて、すべてのJSON列にis json
チェック制約を適用することをお薦めします。
JSON解析のオーバーヘッドは、条件が挿入や更新のパフォーマンスに重大な影響を及ぼさないことを評価するといったもので、制約を除外すると、JSONデータの問合せに単純なドット表記法の構文を使用できないことになります。
何をもって整形式のJSONデータとするかは明確ではありません。実際には、JSONデータには、標準の定義に厳密には従わない特徴がいくつかあることが一般的です。JSONデータの特定の列に、標準の定義(厳密な構文)と、一般的に使用されるJavaScriptのような構文(緩慢な構文)のどちらの構文を必要とするかを制御できます。Oracle Database向けのデフォルトのSQL/JSON構文は緩慢です。どの種類の構文を使用するかは、条件is json
で制御します。JSON列にis json
チェック制約を適用することで、このように緩慢なJSON構文をデフォルトで使用できるようになります。
JSONデータにLOB記憶域を使用する際の考慮事項
JSONデータにLOB記憶域を使用する場合は、CLOB
記憶域ではなくBLOB
を使用することをお薦めします。
これは、データベースのキャラクタ・セットがOracleの推奨値であるAL32UTF8に設定されている場合に、特に該当します。AL32UTF8のデータベースでは、CLOB
インスタンスはUCS2キャラクタ・セットを使用して格納されます。これは、1文字に2バイト必要になることを意味します。ある文書の内容の大半が、キャラクタ・セットAL32UTF8でシングルバイトを使用して表される文字で構成されている場合は、この文書に必要な記憶域が2倍になります。
データベースのキャラクタ・セットがAL32UTF8ではない場合でも、CLOB
ではなくBLOB
の記憶域を選択すると、JSON文書を格納するときにキャラクタ・セットの変換が必要なくなるという利点があります(JSONデータのキャラクタ・セットおよび文字エンコーディングを参照)。
ラージ・オブジェクト(LOB)を使用する場合は、次のようにすることをお薦めします。
-
句
LOB (COLUMN_NAME) STORE AS (CACHE)
をCREATE TABLE
文で使用して、JSON文書の読取り操作が、データベース・バッファ・キャッシュを使用して最適化されるようにします。 -
SecureFiles LOBを使用します。JSONデータに必要な記憶域を減らすために、Oracle Advanced Compressionの使用も検討します。圧縮を使用する場合は、Mediumの圧縮オプションをお薦めします。このオプションは、容量の節約とパフォーマンスの適度なバランスを提供します。
SQL/JSONファンクションおよび条件では、データが格納されるのがBLOB
かCLOB
かという特別な考慮事項なしに、JSONデータを使用できます。アプリケーション開発の観点から見ると、BLOB
コンテンツと連携するためのAPIコールは、CLOB
コンテンツと連携するためのものとほとんど同じです。
CLOB
ではなくBLOB
記憶域を選択する(JSONまたはその他の種類のデータを対象に)マイナス面は、SQL*Plusなどのコマンドライン・ツールを使用したBLOB
コンテンツとの連携がより難しい場合があるということです。次に例を示します。
-
BLOB
列からデータを選択するときに、出力可能なテキストとしてそのデータを表示する場合に、SQLファンクションto_clob
を使用する必要がある。 -
BLOB
列を対象に挿入または更新の操作を実行するときに、SQLファンクションrawtohex
を使用して、文字列を明示的にBLOB
形式に変換する必要がある。Foot 2
関連項目:
-
SQLファンクション
to_clob
の詳細は、Oracle Database SQL言語リファレンスを参照してください -
SQLファンクション
rawtohex
の詳細は、Oracle Database SQL言語リファレンスを参照してください。
クライアントを使用してJSONデータをLOBインスタンスとして取得する場合の考慮事項
Oracle Call Interface (OCI)やJava Database Connectivity (JDBC)などのクライアントで、LOBロケータ・インタフェースを使用してLOBバッチでデータベースからJSONデータを取得する場合は、次の最適化を検討してください。
-
LOBプリフェッチ・サイズを大きい値(65 KBなど)に設定します。
-
フェッチされたLOBを、各行の読取り後に解放します。そうしないと、パフォーマンスが低下し、メモリーがリークする可能性があります。
(ただし、
JSON
型オペランドでの操作からのLOBロケータを使用する場合については、次を参照)。
LOBデータ・インタフェースを使用する場合:
-
OCIでは、
BLOB
データおよびCLOB
データに対してデータ型SQLT_BIN
およびSQLT_CHR
をそれぞれ使用します。 -
JDBCでは、
BLOB
データおよびCLOB
データに対してメソッドgetBytes()
およびgetString()
をそれぞれ使用します。
JSON
型オペランドでのSQL/JSON操作によって戻されたLOBロケータがあるLOBロケータ・インタフェースを使用する場合:
-
LOBは一時的であり読取り専用です。
-
LOBを明示的に解放する必要はありません。次のフェッチで自動的に解放されます。
この例は、JDBCでLOBロケータ・インタフェースを使用する方法を示しています。
Statement stmt = conn.createStatement(); // conn is a java.sql.Connection
stmt.setFetchSize(1000); // Set batch fetch size to 1000 rows
// set LOB prefetch size to be 65 KB
((OraclePreparedStatement)stmt).setLobPrefetchSize(65000);
// Query the JSON data in column jdoc of table myTab, returning JSON data as a BLOB instance
rset = stmt.executeQuery(
"SELECT id, json_serialize(jdoc RETURNING BLOB) FROM myTab");
while (rset.next()) { // Iterate over the returned rows
Blob blob = rset.getBlob (2);
// Do something with the BLOB instance for the row...
// Free the LOB at the end of the iteration.
// Not needed if the LOB is returned by an operation on a
// JSON-type operand, that is, if jdoc is a JSON-type column.
blob.free();
}
rset.close();
親トピック: JSONデータの格納および管理
脚注の凡例
脚注1: 制限がバイト単位かそれとも文字単位かは、セッション・パラメータNLS_LENGTH_SEMANTICS
によって決まります。脚注2: SQLファンクション
rawtohex
の戻り値は32767バイトに制限されています。値は、この長さを超えて変換されたデータをすべて削除するように切り捨てられます。