Oracle 21cにおけるJSON DataTypeのサポート (2021/02/26)

Oracle 21cにおけるJSON DataTypeのサポート (2021/02/26)

https://blogs.oracle.com/jsondb/done-cancel-v22
投稿者:Zhen Hua Liu | Architect
Oracle 21cでは、JSONデータを保存および処理するために、
OSONフォーマットを使用して最適化されたネイティブ・バイナリ・ストレージ・フォーマットであるJSONデータ型が導入されています。
JSONテキスト・ストレージと比較して、より高速なクエリ・パフォーマンス、JSONテキストを解析する必要のないより効率的な更新など、
JSONアプリケーションのパフォーマンス・メリットを提供します。

JSONデータ型は、Oracle Database 21cのテーブル、(マテリアライズされた)ビュー、
PL/SQLプロシージャ/ファンクションパラメータ、戻り値の列として使用することができます。
JDBCとOCIクライアントはバージョン21cでJSONデータ型APIをサポートしています。
SODAコレクションは、JSONデータを格納するためにデフォルトでJSONデータ型を使用します。

次の例は、json データ型カラムを持つテーブルを作成する方法を示しています。

21c (Always Free) Autonoous Databaseでこれらの例を試すことができます。

create table person_collection (id number primary key, jdoc json);

insert into person_collection values(1,
'{"person":{"birthdate":"1998-03-04", "creditscore":[700, 650, 720]}}' );

commit;

Multi-Value関数インデックスとJSON_TRANSFORM()は、
クエリと更新のパフォーマンスを向上させるためにJSONデータ型に特化して設計された21cの新しいJSON機能の2つです。

Multi-Value関数インデックス


21c より前のバージョンでは、ユーザーは JSON_VALUE() の述語評価を高速化するために
単一値の関数型インデックスのみを使用することができます。
関数型インデックスは、以前は行ごとに最大1つの値をインデックス化することに制限されていましたが、
JSONの場合は、フィールドの値が最大1回発生することを意味します。
上記の例では、人は最大1つの "birthdate" フィールドを持っているので、次のような単一値の関数インデックスを作成することができます。

create index birthidx on person_collection t (t.jdoc.person.birthdate.date());

explain plan forselect count(*) from person_collection t
where JSON_VALUE(t.jdoc, '$.person.birthdate' returning date) < :1;

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 0 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 9 | | |
|* 2 | INDEX RANGE SCAN| BIRTHIDX | 1 | 9 | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------

インデックスは単純なドット記法( t.jdoc.person.birthdate.date() )を用いて作成されていますが、
これはインデックスを利用できるJSON_VALUE()演算子と同等のものです。

21cでは、JSON配列内の要素にインデックスを付けるために、JSONデータ型カラムにMulti-Value関数インデックスを作成することができます。
これにより、JSON_EXISTS() - SQL/JSONパス言語の配列比較述語の使用を可能にする演算子 - の評価が高速化されます。

この例では、"person.creditcore "は数値の配列です。
次のような新しい構文を使用して、配列のすべての値にインデックスを作成できるようになりました。

create multivalue index creditsidx on person_collection t (t.jdoc.person.creditscore[*].number());

最後の関数 'number()' は、クレジットスコアの値を数字の羅列として返すので注意してください。
string()' は、値を文字列としてインデックス化するオプションで、 範囲の問い合わせに対して異なる結果を与えます。

explain plan for
select count(*) from person_collection t
where json_exists(t.jdoc, '$.person.creditscore[*]?(@.number() > 700)')
/

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | HASH UNIQUE | | 1 | 13 | | |
|* 3 | INDEX RANGE SCAN (MULTI VALUE)| CREDITSIDX | 1 | 13 | 1 (0)| 00:00:01 |

Multi-Value関数インデックスは、今のところJSONのデータ型カラムでのみサポートされています。


JSON_TRANSFORM()によるJSONの更新


新しい演算子 json_transform() は、JSON テキストの解析のオーバーヘッドなしに
JSON データ型インスタンスを宣言的に更新することをサポートしています。
可能であれば、JSON_TRANSFORMは部分的な更新を行います。
例えば、最初の "creditcore" 値を更新する場合、JOSN_TRANSFORM はディスク上の JSON データの部分的な更新を実行し、ドキュメント全体の完全な更新を回避します。
これは、特に中規模から大規模なJSON文書を更新する場合に、データベースのREDOログサイズを削減するため、パフォーマンスを大幅に向上させます。

update person_collection t
set t.jdoc = json_transform(t.jdoc, set '$.person.creditscore[0]' = 710);

select jdoc from person_collection t

JDOC
--------------------------------------------------------------------------------
{"person":{"birthdate":"1998-03-04","creditscore":[710,650,720]}}


JSONデータ型の既存のSQL/JSON関数



入力としてJSONテキストを受け入れるすべてのSQL/JSONクエリ関数は、JSONデータ型もサポートしています。
すべてのSQL/JSON生成関数はJSONデータ型を生成することができます。
テキストJSONからJSON型インスタンスを生成するには、JSON()という新しいコンストラクタ関数があります。
SQL値からスカラJSON型インスタンスを生成するには、JSON_SCALAR()という新しいコンストラクタ関数が追加されています。
これは、JSON型が追加のデータ型をサポートしているため、DATEやTIMESTAMPの値を保持したJSON型インスタンスを作成することが可能です。
JSONのテキスト表現にはこのような型がサポートされていないため、テキストJSONに変換する際には、
このような値を文字列に変換(シリアライズ)する必要があります。
JSON_SERIALIZE()はJSON型のインスタンスをJSONテキストに変換する関数で、データをきれいに印刷して読みやすくすることができます。


Select JSON_SERIALIZE (jdoc PRETTY) from person_collection
{
"person" :
{
"birthdate" : "1998-03-04",
"creditscore" :
[
710,
650,
720
]
}
}

SQL/JSON関数JSON_QUERYは、入力がJSON型の場合、デフォルトでJSON型を返すようになりました。
入力がJSON型でない場合、既存のデフォルトのVARCHAR2(4000)が維持されます。
概念的には、JSON_QUERYはJSONフラグメントを返すように設計されています - そして、JSON型の入力の場合、フラグメントもJSON型になります。

このデフォルトの変更は、(JSON_QUERYに依存する) JSON単純ドット記法の構文に意味を持ちます - JSON型で評価された場合もJSON型を返すようになります。

2 つの JSON 型は直接比較できないので (Object と Array や Boolean 値を比較するとはどういうことでしょうか?)、
比較可能な SQL 値に変換するためには、単純なドット記法の式の最後に末尾の項目メソッドを提供する必要があります。
これは、単純なドット記法がgroup by、order by、range比較で使用されている場合にも必要です。
そうしないと、JSON 型の値を含む ORA-40796 無効な比較操作が表示されます。

例)
select t.jdoc.person.birthdate.date(), count(*)
from person_collection t
where t.jdoc.person.birthdate.date() between sysdate - 40500 and sysdate
order by t.jdoc.person.birthdate.date();

T.JDOC.PE COUNT(*)
--------- --------
04-MAR-98 1

JSON データ型は、21c データベースのすべてのコンポーネントに完全に統合されています。
JSON検索インデックスJSON_TABLE()マテリアライズドビューJSONデータガイド、並列クエリ処理、
インメモリJSONストアOracle ExaData Smart Scanブロックチェーンテーブルはすべて、
OSON形式を十分に活用してJSONドキュメント処理を高速化するために強化されています。


21c クライアントドライバ Native JSON データ型 サポート



21cクライアントと21cサーバーの間では、テキスト変換なしでJSONデータ型が転送されます。
これにより、クライアントは拡張型(Timestampなど)を使用できるだけでなく、
インジェスト時のJSONエンコードと出力時のテキストシリアライズを回避することでデータベースのCPUを節約できるため、パフォーマンスが大幅に向上します。
また、Oracle 21cクライアントは、JSON APIを直接サポートするために、バイナリJSON形式(OSON)を直接処理することができます
- 例えば、JSONデータ型インスタンス内でナビゲートするために。
JDBC JSONデータ型oracle.sql.jsonインターフェイスを介してサポートし、OCI JSONデータ型C JSON APIをサポートしています。
JSONデータ型を扱う際には、21cクライアント・ドライバを使用することを強く推奨します。
そうしないと、JSONデータ型インスタンスは、バイナリ効率を失うJSONテキストに変換しなければならず、
JSONテキスト表現がサポートできない特定のデータ型をサポートすることができません。
Oracle インスタンス・クライアント・ドライバーはこちらからダウンロードできます。
しかし、Oracle Database 21cで作成されたSODAデフォルトコレクションは、JSON型を利用するために21c SODAドライバを使用しなければなりません。

JSONテキストストレージからJSONデータ型への移行



JSONテキストストレージは、json datatypeへのオンライン再定義移行でJSON datatypeに移行することができます。

コメント

このブログの人気の投稿

Oracle RACによるメンテナンスのためのドレインとアプリケーション・コンティニュイティの仕組み (2023/11/01)

Oracle Cloud Infrastructure Secure Desktopsを発表: デスクトップ仮想化のためのOracleのクラウドネイティブ・サービス (2023/06/28)

新しいOracle Container Engine for Kubernetesの機能強化により、大規模なKubernetesがさらに簡単になりました (2023/03/20)