5.6 二面性ビューのドキュメントに対する操作の最適化
二面性ビューでサポートされているドキュメントに対する操作(具体的には、問合せ)は、自動的に、基になる表データに対する操作としてリライトされます。この最適化には、索引の活用が含まれています。基になるデータの型はすべて認識されているため、暗黙的な実行時型変換は、通常は回避できます。
二面性ビューを問い合せる(つまり、それでサポートされているJSONドキュメントを問い合せる)ことは、JSON
データ型のDATA
という名前の単一列がある表またはビューを問い合せることに似ています。(二面性ビューの非表示列ETAG
およびRESID
を問い合せることもできます。「二面性ビューの作成」を参照してください。)
フィルタ述語(SQL/JSON条件json_exists
を使用)またはSELECT
リスト(SQL/JSONファンクションjson_value
を使用)でJSONドキュメントの値を使用する問合せの場合、基礎となるリレーショナル・データからの中間JSONオブジェクト(JSON
型の列DATA
の場合)の作成は負荷がかかり、不要です。可能な場合は、基礎となる列に格納されているデータに直接アクセスするために、このような問合せが最適化(自動的にリライト)されます。
このドキュメント作成の回避により、パフォーマンスが大幅に向上します。問合せは、JSONドキュメントではなく表データに対して効率的に行われます。ドキュメントは、実際に問合せ結果に必要な場合にのみ作成されます。
ただし、次のような理由で、一部の問合せをリライトすることはできません:
-
問合せパス式には子孫パス・ステップ(
..
)が含まれ、再帰的に、直前のステップに一致するオブジェクトまたは配列(前のステップがない場合はコンテキスト項目)に適用されます。 -
問合せのフィルタ式は、一部の配列要素にのみ適用され、すべて(
[*]
)には適用されません。たとえば、[3]
は4番目の配列要素にのみ適用され、[last]
は最後の要素にのみ適用されます。 -
問合せパス式には、否定されたフィルタ式が含まれています。『Oracle Database JSON開発者ガイド』のパス式での否定を参照してください。
SQL/JSONファンクションjson_value
、json_query
およびjson_exists
を使用する二面性ビューの問合せの場合、パラメータJSON_EXPRESSION_CHECK
をON
に設定すると、問合せを自動的にリライトできない場合、その理由を示すエラーが発生します。
JSON_EXPRESSION_CHECK
は、簡単な誤字を指摘する場合にも役立ちます。SQL/JSONパス式またはドット表記法構文でJSONフィールド名の不一致を検出してレポートします。
パラメータJSON_EXPRESSION_CHECK
は、(1)データベース初期化ファイル(init.ora
)、(2) ALTER SESSION
またはALTER SYSTEM
文、または(3) SQL問合せヒント(/*+ opt_param('json_expression_check', 'on') */
)を使用して設定できます。Oracle DatabaseリファレンスのJSON_EXPRESSION_CHECKを参照してください。
場合によっては、コードで明示的に型変換がコールされることがあり、それにより、リライトでの最適化によって最適にならず、不要な実行時オーバーヘッドが発生する可能性があります。これは、たとえば、SQL/JSONファンクションjson_value
の場合に起こる可能性があります。デフォルトでは、そのSQLの戻り型はVARCHAR2
です。たとえば、その値が、基になる表列(型はNUMBER
)に使用される予定の場合は、不要な実行時型変換が発生する可能性があります。
このため、最良のパフォーマンスにするには、一般的ガイドラインとして、ドキュメント・フィールド値に実行時型変換が必要ないことを示すRETURNING
句または型変換SQL/JSON項目メソッドを使用することをお薦めします。その型として、対応付けられた基になる列で使用されているのと同じ型を指定します。
たとえば、レース・ドキュメント内のフィールド_id
は、基になるrace
表内の列race_id
に対応付けられており、その列のSQL型はNUMBER
です。このため、json_value
を使用してフィールド_id
を選択またはテストするときに、NUMBER
値が返されるようにする必要があります。
次の2つの問合せの2番目は、通常は、1番目よりもパフォーマンスが高くなります。これは、1番目の問合せではjson_value
からVARCHAR2
値が戻されて、実行時にそれがNUMBER
値およびDATE
値に変換されるためです。2つ目の例では、型変換SQL/JSON項目メソッドnumberOnly()
とRETURNING DATE
句を使用して、使用するSQL型がNUMBER
およびDATE
であることを問合せコンパイラに示します。(型変換項目メソッドを使用することは、対応するRETURNING
型を使用することと同じです。)
SELECT json_value(DATA, '$.laps'),
json_value(DATA, '$.date')
FROM race_dv
WHERE json_value(DATA, '$._id') = 201;
SELECT json_value(DATA, '$.laps.numberOnly()'),
json_value(DATA, '$.date' RETURNING DATE)
FROM race_dv
WHERE json_value(DATA, '$._id.numberOnly()') = 201;
同じ一般的ガイドラインが、単純ドット表記法構文の使用にも当てはまります。自動最適化は、通常は、ドット表記法の構文がWHERE
句で使用されている場合に実行されます: ドット表記法の式で対象となったデータは、その対象データの比較先の値の型に型キャストされます。ただし、問合せコンパイル時に、関連する型を推測できないことがあります。たとえば、比較する値が、実行時まで型が不明なSQL/JSON変数($a
など)から取得される場合です。関連する項目メソッドを追加して、想定される入力が問合せコンパイル時に明確になるようにします。
次の2つの問合せの2番目は、ガイドラインに従っています。これは通常は、1番目よりもパフォーマンスが高くなります。その理由は、SELECT
およびORDER BY
句で項目メソッドnumberOnly()
およびdateTimeOnly()
が使用され、適切なデータ型が指定されているためです。脚注1
SELECT t.DATA.laps, t.DATA."date"
FROM race_dv t
WHERE t.DATA."_id" = 201
ORDER BY t.DATA."date";
SELECT t.DATA.laps.numberOnly(), t.DATA."date".dateTimeOnly()
FROM race_dv t
WHERE t.DATA."_id".numberOnly() = 201
ORDER BY t.DATA."date".dateTimeOnly();
関連項目:
-
『Oracle Database JSON開発者ガイド』の項目メソッドによるデータ型変換
-
『Oracle Database JSON開発者ガイド』の項目メソッドとJSON_VALUE RETURNING句
親トピック: JSONリレーショナル二面性ビューの使用
脚注一覧
脚注1: この例では、SQLの単純なドット表記法を使用します。_id
がSQL/JSONパス式にありません。そのため、それを二重引用符文字("
)で囲む必要があります。これは、それがアンダースコア文字(_
)であるためです。