27 JSONデータの索引
関数ベースの索引を使用すると、JSONデータのスカラー値を索引付けできます。また、JSON検索索引を定義できます。これは、非定型の構造的問合せと全文問合せの両方に便利です。
- JSONデータの索引付けの概要
非定型の構造的問合せおよび全文問合せ用に、JSON検索索引を使用して通常の方法でJSONデータを索引付けできます。関数ベースの索引を使用して、JSONデータ内の特定のスカラー値を索引付けすることもできます。 - JSONデータに対して関数ベースの索引が選択されるかどうかを確認する方法
特定の問合せで特定の関数ベースの索引が選択されるかどうかを確認するには、問合せの実行計画内で索引名を検索します。 - JSON_VALUEのためのビットマップ索引の作成
SQL/JSONファンクションjson_value
のためにビットマップ索引を作成できます。ビットマップ索引は、問合せが小さいセットのJSON値のみを対象にしている場合に適しています。 - JSON_VALUEのためのBツリー索引の作成
SQL/JSONファンクションjson_value
のために、Bツリーの関数ベースの索引を作成できます。これを行うには、標準構文を使用してjson_value
を明示的に指定するか、項目メソッドを持つドット表記法構文を使用できます。これらいずれかの方法で作成された索引は、ドット表記法問合せとjson_value
問合せのどちらとも一緒に使用できます。 - JSON_VALUE関数ベースの索引とJSON_TABLE問合せの使用
ERROR ON ERROR
を指定したjson_value
を使用して作成された索引は、json_table
を含む問合せに使用できます。この場合、この索引が索引付きパスに対する制約として機能することにより、JSONコレクション内の各項目に対して1つの(非null
の)スカラーのJSON値のみが確実に投影されるようになります。 - JSON_VALUE関数ベースの索引とJSON_EXISTS問合せの使用
ERROR ON ERROR
を指定したSQL/JSONファンクションjson_value
を使用して作成された索引は、SQL/JSON条件json_exists
を含む問合せに使用できます。 - JSON_VALUEの索引付けおよび問合せに関するデータ型の考慮事項
SQL/JSONファンクションjson_value
を使用して作成されたファンクション・ベースの索引では、問合せでjson_value
によって返されたデータ型が索引で指定された型と一致する必要があります。 - コンポジットBツリー索引を使用した複数のJSONフィールドの索引付け
JSONオブジェクトの複数のフィールドを索引付けするには、SQL/JSONファンクションjson_value
またはドット表記法構文に複数のパス式を使用して、コンポジットBツリー索引を作成します。 - 非定型の問合せおよび全文検索のためのJSON検索索引
JSON検索索引は、一般的な索引です。この検索索引によって、(1)非定型の構造的問合せ、つまり、定期的には予測または使用されない可能性のある問合せと、(2)全文検索の両方のパフォーマンスを向上させることができます。これは、JSONデータでの使用に特化して設計されたOracle Text索引です。
親トピック: JSON用のパフォーマンス・チューニング
27.1 JSONデータの索引付けの概要
非定型の構造的問合せおよび全文問合せ用に、JSON検索索引を使用して通常の方法でJSONデータを索引付けできます。関数ベースの索引を使用して、JSONデータ内の特定のスカラー値を索引付けすることもできます。
SQL/JSONファンクションjson_value
のためにBツリー索引またはビットマップ索引を使用できます。関数で想定される値の数が少ない場合は、常にビットマップ索引が適しています。たとえば、対象となる値が少数であると予想される場合は、json_value
のためにビットマップ索引を使用できます。
この場合も、このような関数ベースの索引付けは、特定の関数を対象とする問合せに適していますが、これは、SQL/JSONファンクションのコンテキストでは特定のSQL/JSONパス式を意味します。これは、非定型(つまり、任意)の問合せの場合はあまり役に立ちません。関数ベースの索引を定義するのは、特定のパス式を何度も問い合せることがわかっている場合にしてください。
述語を含むSQL/JSONパス式は、関数ベースの索引が選択される問合せに使用できますが、関数ベースの索引を定義するために使用するパス式には、述語を含めることはできません。そうしないと、索引の作成時にエラーが発生します。
非定型方式で問い合せる場合は、JSON検索索引を定義してください。これは、一般的索引であり、特定のパス式の対象ではありません。これは、構造問合せ(特定の値を持つJSONフィールドを検索する場合など)や、Oracle SQL条件json_textcontains
を使用した全文問合せ(様々な文字列値から特定の単語を検索する場合など)に適しています。
同じJSON列に対して関数ベースの索引とJSON検索索引を定義することもできます。
JSON検索索引は、JSONデータでの使用に特化して設計されたOracle Text (全文)索引です。
注意:
データベース・キャラクタ・セットとしてAL32UTF8を使用することをお薦めします。索引の作成または適用時に、キャラクタ・セットの自動変換が行われる場合があります。このような変換では情報が失われる可能性があります。これは、問合せで戻されることが予測されるデータが、戻されない場合があることを意味します。JSONデータのキャラクタ・セットおよび文字エンコーディングを参照してください。
親トピック: JSONデータの索引
27.2 JSONデータに対して関数ベースの索引が選択されるかどうかを確認する方法
特定の問合せで特定の関数ベースの索引が選択されるかどうかを確認するには、問合せの実行計画内で索引名を検索します。
親トピック: JSONデータの索引
27.3 JSON_VALUEのためのビットマップ索引の作成
SQL/JSONファンクションjson_value
に対してビットマップ索引を作成できます。ビットマップ索引は、問合せが小さいセットのJSON値のみを対象にしている場合に適しています。
例27-1 JSON_VALUEのビットマップ索引の作成
データ内のフィールドCostCenter
に対して想定される値が少ない場合、これは作成に適した索引です。
CREATE BITMAP INDEX cost_ctr_idx ON j_purchaseorder
(json_value(po_document, '$.CostCenter'));
親トピック: JSONデータの索引
27.4 JSON_VALUEのためのBツリー索引の作成
SQL/JSONファンクションjson_value
のために、Bツリーの関数ベースの索引を作成できます。これを行うには、標準構文を使用してjson_value
を明示的に指定するか、項目メソッドを持つドット表記法構文を使用できます。これらいずれかの方法で作成された索引は、ドット表記法問合せとjson_value
問合せのどちらとも一緒に使用できます。
例27-3では、表j_purchaseorder
の列po_document
内にあるオブジェクトのフィールドPONumber
に対するjson_value
の関数ベースの索引を作成しています。オブジェクトはパス式のコンテキスト項目として渡されます。
ここでERROR ON ERROR
を使用することは、フィールドPONumber
がないレコード、複数のPONumber
フィールドを持つレコードまたは非数値の値を持つPONumber
フィールドがあるレコードがデータに含まれる場合、索引の作成が失敗することを意味します。また、索引が存在する場合、このようなレコードを挿入しようとしても失敗します。
代替の方法としては、JSONデータに対する単純なドット表記法アクセスで説明されているように、ドット表記法構文を使用して対象となるデータに項目メソッドを適用して索引を作成する方法があります。例27-2に、これを示します。
例27-3と例27-2の両方で作成された索引は、ドット表記法構文を使用する問合せとjson_value
を使用する問合せのいずれかに対して選択できます。
json_value
式の対象のフィールドで欠落している可能性のあるデータの索引付けを許可する場合は、NULL ON EMPTY
句をERROR ON ERROR
句と一緒に使用します。例27-4に、これを示します。
次のいずれかの形式を使用してjson_value
に対して関数ベースの索引を作成することをお薦めします。どちらの場合も、指定されたJSONデータ型のスカラーの結果となるドット表記法およびjson_value
問合せの両方で、索引を使用できます。
-
項目メソッドが索引付けされる値に適用されるドット表記法構文。索引付けされる値は、項目メソッドで指定されたデータ型のスカラーのみです。
-
RETURNING
のデータ型を指定するjson_value
式。必要に応じて、ERROR ON ERROR
およびNULL ON EMPTY
を使用できます。索引付けされる値は、RETURNING
句で指定されたデータ型のスカラーのみです。
このように、これらいずれかの方法で作成された索引は、ドット表記法問合せとjson_value
問合せのどちらとも一緒に使用できます。
例27-2 JSONフィールドに対する関数ベースの索引の作成: ドット表記法
項目メソッドnumber()
を使用すると、数値型の索引が作成されます。ドット表記法を使用して関数ベースの索引を作成する場合は、対象データに項目メソッドを常に適用します。
CREATE UNIQUE INDEX po_num_idx2 ON j_purchaseorder po
(po.po_document.PONumber.number());
例27-3 JSONフィールドに対する関数ベースの索引の作成: JSON_VALUE
項目メソッドnumber()
を使用すると、数値型の索引が作成されます。かわりに、RETURNING NUMBER
句を使用することもできます。
CREATE UNIQUE INDEX po_num_idx1 ON j_purchaseorder
(json_value(po_document, '$.PONumber.number()'
ERROR ON ERROR));
例27-4 JSON_VALUE関数ベースの索引に対するNULL ON EMPTYの指定
RETURNING VARCHAR2(200)
句を指定すると、索引は最大長200文字のSQL文字列になります。かわりにパス式に項目メソッドstring()
を使用できますが、その場合は、デフォルトの戻り型VARCHAR2(4000)
が使用されます。
句NULL ON EMPTY
が指定されているため、索引po_ref_idx1
は、Reference
フィールドがないJSON文書にも索引を付けることができます。
CREATE UNIQUE INDEX po_ref_idx1 ON j_purchaseorder
(json_value(po_document, '$.Reference'
RETURNING VARCHAR2(200) ERROR ON ERROR
NULL ON EMPTY));
27.5 JSON_VALUE関数ベースの索引とJSON_TABLE問合せの使用
ERROR ON ERROR
を指定したjson_value
を使用して作成された索引は、json_table
を含む問合せに使用できます。この場合、この索引が索引付きパスに対する制約として機能することにより、JSONコレクション内の各項目に対して1つの(非null
の)スカラーのJSON値のみが確実に投影されるようになります。
この方法で索引を使用する場合は、次の各条件が満たされている必要があります。
-
問合せの
WHERE
句は、json_table
によって投影される列を参照する。 -
その列のデータ型は、索引定義に使用されたデータ型と一致する。
-
その列を対象とする有効なSQL/JSONパスが、索引付けされたパス式と一致する。
したがって、例27-5の問合せでは、例27-3で作成された索引を使用しています。
注意:
json_value
式またはドット表記法を使用して作成された関数ベースの索引を、問合せでWHERE
句が出現するたびに取得できるのは、この発生がSQLの比較条件(>=
など)で使用されている場合のみです。特に、これは、条件IS NULL
またはIS NOT NULL
で使用される存在としては選択されません。
SQL比較条件の詳細は、Oracle Database SQL言語リファレンスを参照してください。
例27-5 JSON_VALUE関数ベースの索引とJSON_TABLE問合せの使用
列のSQL型NUMBER(5)
が索引に使用されている型と一致するため、索引を選択できます。
SELECT jt.*
FROM j_purchaseorder po,
json_table(po.po_document, '$'
COLUMNS po_number NUMBER(5) PATH '$.PONumber',
reference VARCHAR2(30 CHAR) PATH '$.Reference',
requestor VARCHAR2(32 CHAR) PATH '$.Requestor',
userid VARCHAR2(10 CHAR) PATH '$.User',
costcenter VARCHAR2(16 CHAR) PATH '$.CostCenter') jt
WHERE po_number = 1600;
親トピック: JSONデータの索引
27.6 JSON_VALUE関数ベースの索引とJSON_EXISTS問合せの使用
ERROR ON ERROR
を指定したSQL/JSONファンクションjson_value
を使用して作成された索引は、SQL/JSON条件json_exists
を含む問合せに使用できます。
問合せの比較のいずれかでjson_value
関数ベースの索引が選択されるためには、その比較の型が、索引のSQL戻りデータ型と同じである必要があります。使用されるSQLデータ型は、double()
、float()
、number()
、string()
、timestamp()
、date()
、dateWithTime()
、dsInterval()
およびymInterval()
の項目メソッドで言及されたデータ型です(SQL/JSONパス式の項目メソッドを参照)。
たとえば、索引で数値が戻される場合は、比較の型も数値である必要があります。問合せのフィルタ式に、json_value
索引と一致する複数の比較が含まれる場合は、これらの索引の1つがオプティマイザによって選択されます。
比較の型は、次のように決まります。
-
2つの比較語(比較の両側)のSQLデータ型が異なる場合、比較の型は不明になり、索引は選択されません。両方の型が同じ場合は、その型が比較の型になります。
-
1つの比較語のSQLデータ型が文字列(テキスト・リテラル)である場合、比較の型は、もう一方の比較語の型になります。
-
1つの比較語が、項目メソッドによってSQLの一致型が強制される関数ステップを持つパス式の場合、その型も比較語の型になります。SQLの一致型が強制される項目メソッドは、
double()
、float()
、number()
、string()
、timestamp()
、date()
、dateWithTime()
,dsInterval()
およびymInterval()
です。 -
1つの比較語が、前述のような関数ステップを持たないパス式の場合、その型はSQL文字列(テキスト・リテラル)になります。
例27-3では、フィールドPONumber
のjson_value
に対するファンクションベースの索引を作成します。この索引は、NUMBER
値に索引付けします。
例27-6、例27-7および例27-8のそれぞれの問合せでは、json_exists
条件を評価するときにこの索引を使用できます。これらの各問合せで、絶対パス式$.PONumber
に相対的な単純なパス式に関連する比較が使用されます。それぞれの場合の単純な相対パス式は、カレント・フィルタ項目(@
)を対象としますが、例27-8の場合は、照合データをSQLデータ型NUMBER
に変換(キャスト)します。
例27-6 リテラル数値と比較したフィールドを対象としたJSON_EXISTS問合せ
この問合せでは、次の理由から索引が利用されます。
-
1つの比較語が、関数ステップを持たないパス式であるため、その型はSQL文字列(テキスト・リテラル)である。
-
1つの比較語が文字列型であるため、比較の型はもう一方の語の型になり、その型が数値である(もう一方の語は数字)。
-
(唯一の)比較の型が、索引で戻される型(数値)と同じである。
SELECT count(*) FROM j_purchaseorder
WHERE json_exists(po_document, '$.PONumber?(@ > 1500)');
例27-7 変数値と比較したフィールドを対象としたJSON_EXISTS問合せ
この問合せでは、次の理由から索引を利用できます。
-
1つの比較語が、関数ステップを持たないパス式であるため、その型はSQL文字列(テキスト・リテラル)である。
-
1つの比較語が文字列型であるため、比較はもう一方の語の型を持つことになり、この型が数値である(もう一方の語は、数値にバインドされた変数)。
-
(唯一の)比較の型が、索引で戻される型(数値)と同じである。
SELECT count(*) FROM j_purchaseorder
WHERE json_exists(po_document, '$.PONumber?(@ > $d)'
PASSING 1500 AS "d");
例27-8 変数値と比較して数値にキャストされるフィールドを対象としたJSON_EXISTS問合せ
この問合せでは、次の理由から索引を利用できます。
-
1つの比較語が、項目メソッド(
number()
)によって照合データが数値に変換される関数ステップを持つパス式であるため、比較語の型はSQL数値である。 -
もう一方の比較語が、SQL型数値を持つ数値である。比較語の型が一致しているため、比較も同じ型である数値になる。
-
(唯一の)比較の型が、索引で戻される型(数値)と同じである。
SELECT count(*) FROM j_purchaseorder
WHERE json_exists(po_document, '$.PONumber?(@.number() > $d)'
PASSING 1500 AS "d");
例27-9 フィールド比較の論理積を対象としたJSON_EXISTS問合せ
例27-6と同様に、この問合せではフィールドPONumber
の索引を利用できます。json_value
索引がフィールドReference
に対しても定義されている場合、オプティマイザがこの問合せに対してどちらの索引を使用するかを選択します。
SELECT count(*) FROM j_purchaseorder
WHERE json_exists(po_document, '$?(@.PONumber > 1500
&& @.Reference == "ABULL-20140421")');
親トピック: JSONデータの索引
27.7 JSON_VALUEの索引付けおよび問合せに関するデータ型の考慮事項
SQL/JSONファンクションjson_value
を使用して作成されたファンクション・ベースの索引では、問合せでjson_value
によって返されたデータ型が索引で指定された型と一致する必要があります。
RETURNING DATE
がjson_value
とともに使用される場合、索引が選択されるためには、同じ時間処理動作(切捨てまたは保存)を索引と問合せの両方で使用する必要があります。つまり、両方でRETURNING DATE PRESERVE TIME
を使用するか、両方でRETURNING DATE TRUNCATE TIME
(または、切捨てがデフォルトの動作であるためRETURNING DATE
)を使用する必要があります。
デフォルトでは、SQL/JSONファンクションjson_value
はVARCHAR2
値を戻します。json_value
を使用して関数ベースの索引を作成する場合、RETURNING
句または項目メソッドを使用して異なる戻りデータ型を指定しないかぎり、非VARCHAR2
値を想定する問合せに対してこの索引は選択されません。
たとえば、例27-10の問合せの場合、json_value
でRETURNING NUMBER
が使用されています。この問合せには例27-3で作成された索引を選択できますが、これは、索引が付けられたjson_value
式で戻り型としてNUMBER
が指定されているためです。索引にキーワードRETURNING NUMBER
が指定されていない場合、指定される戻り型はVARCHAR2(4000)
(デフォルト)になり、そのような問合せに対して索引は選択されません。
同様に、例27-2で作成された索引は、項目メソッドnumber()
(戻り型NUMBER
が強制されます)を使用しているので、この問合せに対して選択される可能性があります。
ここで、戻される値の型がVARCHAR2
になるようにRETURNING
句なしでjson_value
を使用している例27-11と例27-12の問合せについて検討してみます。
例27-11では、SQL関数to_number
により、json_value
によって戻されるVARCHAR2
値を数値に明示的に変換しています。同様に、例27-12では、比較条件> (より大きい)により、値を数値に暗黙的に変換しています。
例27-3と例27-2の索引のいずれも、これらの問合せに対して選択されません。これらの問合せでは、いずれの事例でも型キャストのために正しい結果が戻される可能性がありますが、これらの索引を使用してこれらの問合せを評価することはできません。
また、一部のデータを特定のデータ型に変換できない場合に何が起きるかについても検討してください。たとえば、例27-10、例27-11および例27-12の問合せが実行された場合、"alpha"
などのPONumber
値はどうなるでしょうか。
例27-11および例27-12の場合、値を数値にキャストしようとするために問合せはエラーで停止します。ただし、例27-10の場合、デフォルトのエラー処理動作がNULL ON ERROR
であるため、非数値"alpha"
は単純にフィルタで除外されます。値には索引が付けられますが、問合せに対しては無視されます。
同様に、たとえばDEFAULT '1000' ON ERROR
が問合せで使用されたとすると、つまり、数値のデフォルト値が指定されたとすると、値"alpha"
に対してエラーは発生しません。この場合、デフォルト値の1000
が使用されます。
注意:
指定された問合せに対してSQL/JSONファンクションjson_value
に基づくファンクション・ベースの索引が選択されるためには、索引と問合せの両方で同じ戻りデータ型および処理方法(エラー、空、不一致)を使用する必要があります。
つまり、問合せの戻り型または処理方法を変更して、索引に指定されたものと一致しないようにする場合は、問合せパターンに依存する永続オブジェクトを再構築する必要があります。(同じことが、マテリアライズド・ビュー、パーティション、チェック制約およびそのパターンに依存するPL/SQLサブプログラムにも当てはまります。)
例27-10 JSON_VALUE問合せと明示的なRETURNING NUMBER
SELECT count(*) FROM j_purchaseorder po
WHERE json_value(po_document, '$.PONumber' RETURNING NUMBER) > 1500;
例27-11 JSON_VALUE問合せと明示的な数値変換
SELECT count(*) FROM j_purchaseorder po
WHERE to_number(json_value(po_document, '$.PONumber')) > 1500;
例27-12 JSON_VALUE問合せと暗黙的な数値変換
SELECT count(*) FROM j_purchaseorder po
WHERE json_value(po_document, '$.PONumber') > 1500;
親トピック: JSONデータの索引
27.8 コンポジットBツリー索引を使用した複数のJSONフィールドの索引付け
JSONオブジェクトの複数のフィールドを索引付けするには、SQL/JSONファンクションjson_value
またはドット表記法構文に複数のパス式を使用して、コンポジットBツリー索引を作成します。
例27-13に、これを示します。対応するJSONデータ(オブジェクト・フィールド)を参照するSQL問合せでは、コンポジット索引が選択されます。例27-14に、これを示します。
または、索引付けするJSONオブジェクトのフィールドの仮想列を作成し、それらの仮想列にコンポジットBツリー索引を作成できます。その場合、仮想列または対応するJSONデータ(オブジェクト・フィールド)を参照するSQL問合せでは、コンポジット索引が選択されます。問合せパフォーマンスはどちらの場合も同じです。
問合せのパフォーマンスを向上させるために実装された索引に、データが論理的に依存することはありません。この実装からの独立をコードに反映するには、(仮想列ではなく)データを直接問い合せます。このようにすることにより、問合せは索引の有無とは関係なく同様に機能します。この場合、索引はパフォーマンスの向上に特化して機能します。
例27-13 JSONオブジェクト・フィールドのコンポジットBツリー索引の作成
CREATE INDEX user_cost_ctr_idx on j_purchaseorder(json_value(po_document, '$.User' RETURNING VARCHAR2(20),
json_value(po_document, '$.CostCenter' RETURNING VARCHAR2(6)));
例27-14 コンポジット索引を使用して索引付けされたJSONデータの問合せ
SELECT po_document FROM j_purchaseorder
WHERE json_value(po_document, '$.User') = 'ABULL'
AND json_value(po_document, '$.CostCenter') = 'A50';
親トピック: JSONデータの索引
27.9 非定型の問合せおよび全文検索のためのJSON検索索引
JSON検索索引は、一般的な索引です。この検索索引によって、(1)非定型の構造的問合せ、つまり、定期的には予測または使用されない可能性のある問合せと、(2)全文検索の両方のパフォーマンスを向上させることができます。これは、JSONデータでの使用に特化して設計されたOracle Text索引です。
注意:
JSON
型として格納されているJSONデータの場合、JSON検索索引を作成して保守することの代替の方法としては、インメモリー列ストア(IM列ストア)にJSON列を移入する方法があります。
非定型問合せをサポートするには、キーワードTEXT
を使用せずに、列またはその表をIM列ストアに配置します。全文検索をサポートするには、キーワードTEXT
を使用して、列をIM列ストアに配置します。両方の種類の問合せをサポートするには、両方を行うことができます。(JSON
型は、データベース初期化パラメータcompatible
が少なくとも20
である場合にのみ使用できます。)
JSON
型の列をIM列ストアに配置し、それにJSON検索索引を定義した場合、非定型問合せと全文問合せの両方で検索索引のみが使用されます。検索索引はIM列ストアの使用よりも常に優先されます。
注意:
JSON検索索引を作成してある場合、PL/SQLプロシージャCTX_QUERY.result_set
を使用して、索引付けされたJSONデータの別の種類の全文検索(ファセット検索)を実行することもできます。
CTX_QUERY
検索は、たとえばSQLファンクションcontains
により複数の個別問合せを使用するのではなく、様々な種類の検索ヒットをすべて一度に生成するように最適化されています。
これらのプロシージャのいずれかを使用して検索するには、結果セット・ディスクリプタ(RSD)を渡します。これにより、(事前定義済演算子フィールド$query
、$search
および$facet
を含むJSONオブジェクトとして)索引付けされたJSONデータから検索するJSON値と、そのグループ化または集計方法が指定されます。取得および処理できる値は、JSONスカラーまたはJSONのスカラーの配列のいずれかです。
(演算子フィールド$query
は、SODA query-by-example (QBE)問合せでも使用されます。演算子$contains
を、フィールド$query
の値内に、Oracle SQL条件json_textcontains
で提供されるのと同様の全文照合のために使用できます。)
RSDフィールドは、出力結果セットに含める内容を指定する順序付きテンプレートとして機能します。(検出されたJSONデータに加えて、結果セットには通常、検索ヒットしたrowidといくつかのカウントのリストが含まれています。)
$facet
フィールド値はファセット・オブジェクトのJSON配列です。それぞれのオブジェクトが、特定のパスにあるJSONデータを定義し、場合によっては一部の条件を満たし、そのデータに適用する集計操作を定義しています。
ファセット・データは、演算子$count
、$min
、$max
、$avg
および$sum
を使用して集計できます。たとえば、$sum
は、ターゲット・データ値の合計を返します。集計演算子は、パスによって対象指定されたすべてのスカラー値に適用するか、または様々な値範囲で定義されたそのような値のバケットに個別に適用できます。
最後に、演算子$uniqueCount
を使用して、指定のパスでの個別値の出現回数を取得できます。
たとえば、次の$facet
値について考えてみます。
[{"$uniqueCount" : "zebra.name"},
{"$sum" : {"path" : "zebra.price",
"bucket : [{"$lt" : 3000},
{"$gte" : 3000}]},
{"$avg" : "zebra.rating"}]
問合せ結果が返されると、出力内のフィールド$facet
の値は3つのオブジェクトの配列であり、次のフィールドが含まれています。
-
zebra.name
— 各zebra名の出現回数。 -
zebra.price
— 2つのバケット(3000未満の価格と3000以上の価格)で表したzebra価格の合計。 -
zebra.rating
— すべてのzebra評価の平均。(評価のないzebraは無視されます。)
[{"zebra.name" : [{"value" : "Zigs", "$uniqueCount : 2},
{"value" : "Zigzag", "$uniqueCount : 1},
{"value" : "Storm", "$uniqueCount : 1}]},
{"zebra.price" : [{"value" : 1000, "$uniqueCount : 2},
{"value" : 3000, "$uniqueCount : 2},
{"value" : 2000, "$uniqueCount : 1}]},
{"zebra.rating" : {"$avg" : 4.66666666666666666667}}]
注意:
Oracle Database 12cリリース1 (12.1.0.2)を使用してJSON検索索引を作成した場合は、その索引を削除し、以降のリリースで使用するために、ここで説明するCREATE SEARCH INDEX
を使用して検索索引を新しく作成することをお薦めします。
CREATE SEARCH INDEX
にキーワードFOR JSON
を指定して、JSON検索索引を作成します。例27-15に、これを示します。
JSON検索索引を作成する列は、JSON
、VARCHAR2
、CLOB
またはBLOB
データ型の列です。整形式のJSONデータのみが含まれていることが認識されている必要があります(つまり、JSON
型であるか、is json
チェック制約がある)。列にJSONデータが含まれていることを認識できない場合、CREATE SEARCH INDEX
でエラーが発生します。
問合せの実行計画内にJSON検索索引の名前が存在する場合、索引が実際に問合せに対して選択されたことがわかります。例27-17に示すものと似た行が表示されます。
特定の構成可能なオプションのデフォルト設定をオーバーライドする場合は、検索索引の作成時にPARAMETERS
句を指定できます。デフォルト(PARAMETERS
句なし)では、索引はコミット時に同期化され、テキストと数値の範囲の両方が索引付けされます。
JSON検索索引は非同期にメンテナンスされます。同期されるまで、この索引は変更されたデータまたは新しく挿入されたデータに使用されません。索引を使用すると問合せのパフォーマンスが向上しますが、データと同期する処理の実行中はパフォーマンスに悪影響します。特に、DML操作に対して悪影響することがあります。
JSON検索索引を同期するには、基本的に3つの方法があります。通常、それぞれの方法は異なるユースケースに適しています。
-
コミット時に同期。
これは、コミットが頻繁に行われず、コミットされた変更を他の操作(問合せなど)がすぐに参照できることが重要である場合に適しています。(索引が失効していると、コミットされていない変更を参照できないことがあります。)例27-15では、コミット時に同期される検索索引を作成します。
-
一定の間隔で定期的に同期。
高速で信頼性の高いトランザクション処理で高いスループットが求められるオンライン・トランザクション処理(OLTP)アプリケーションでは、通常、各操作をコミットするため、定期的に索引を同期することが適しています。この場合、通常、同期の間隔は各コミットの間の時間より長くします。各コミットの結果が他の操作によってすぐに参照可能になることは重要ではありません。例27-16では、毎秒同期される検索索引を作成します。
-
オンデマンドで同期(たとえば、データベースの負荷が減少したとき)。
通常、これは頻繁に実行しません。コミット時の同期または間隔での同期よりも少ない頻度で、索引が同期されます。DMLのパフォーマンスが特に重要な場合は、この方法が一般的に適しています。
JSON検索索引を作成するには、CTXAPP
権限が必要となります。索引をコミット時に同期するのではなく、同期の間隔を使用して索引を作成する場合は、CREATE JOB
権限も必要となります。
JSON検索索引を利用する問合せで数値の範囲が使用されない場合は、パラメータSEARCH_ON
にTEXT
を指定すると、メンテナンスの時間とディスク領域をいくらか節約できます。SEARCH_ON
のデフォルト値はTEXT_VALUE
です。これは、テキストと同様に索引の数値の範囲も意味します。
注意:
JSON検索索引j_s_idx
を変更するには、ALTER INDEX j_s_idx REBUILD ...
(ALTER SEARCH INDEX j_s_idx ...
ではない)を使用します。
例27-15 コミット時に同期されるJSON検索索引の作成
コミット時の同期はデフォルトの動作ですが、PARAMETERS ('SYNC (ON COMMIT)'
を使用して明示的に指定できます。
CREATE SEARCH INDEX po_search_idx ON j_purchaseorder (po_document)
FOR JSON;
例27-16 毎秒同期されるJSON検索索引の作成
CREATE SEARCH INDEX po_search_1_sec_idx ON j_purchaseorder (po_document)
FOR JSON
PARAMETERS('SYNC (EVERY "FREQ=SECONDLY; INTERVAL=1")
例27-17 JSON検索索引が使用されていることを示す実行計画
|* 2| DOMAIN INDEX | PO_SEARCH_IDX | | | 4 (0)
例27-18 いくつかの非定型JSON問合せ
この問合せでは、船積み依頼書の住所に国が含まれる文書を選択します。
SELECT po_document FROM j_purchaseorder
WHERE json_exists(po_document, '$.ShippingInstructions.Address.country');
この問合せでは、ユーザーAKHOO
が含まれる文書で、注文された項目が8個より多いものを選択します。ここでは、数値範囲の索引付けが利用されます。
SELECT po_document FROM j_purchaseorder
WHERE json_exists(po_document, '$?(@.User == "AKHOO"
&& @.LineItems.Quantity > 8)');
この問合せでは、ユーザーがAKHOO
の文書が選択されます。ここでは、WHERE
句で、json_exists
のかわりにjson_value
が使用されます。
SELECT po_document FROM j_purchaseorder
WHERE json_value(po_document, '$.User') = 'AKHOO';
関連項目:
-
CREATE SEARCH INDEX
のPARAMETERS
句の詳細は、Oracle Textリファレンスを参照してください。 -
ALTER INDEX
...REBUILD
のPARAMETERS
句の詳細は、Oracle Textリファレンスを参照してください。 -
JSON検索索引の同期化の詳細は、Oracle TextリファレンスのCREATE INDEXを参照してください。
-
JSON検索索引のパフォーマンスの最適化および調整の詳細は、Oracle Textアプリケーション開発者ガイドを参照してください。
親トピック: JSONデータの索引