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_valuejson_queryおよびjson_existsを使用する二面性ビューの問合せの場合、パラメータJSON_EXPRESSION_CHECKONに設定すると、問合せを自動的にリライトできない場合、その理由を示すエラーが発生します。

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();

関連項目:



脚注一覧

脚注1: この例では、SQLの単純なドット表記法を使用します。_idがSQL/JSONパス式にありません。そのため、それを二重引用符文字(")で囲む必要があります。これは、それがアンダースコア文字(_)であるためです。