問合せ計画の概要

問合せ実行計画は、内部的には計画イテレータのツリーとして構造化されます。

各種のイテレータは、問合せに出現する様々な種類の式を評価します。通常、索引の選択および関連する索引条件の種類は、問合せのパフォーマンスに大きく影響する可能性があります。そのため開発者は、多くの場合、問合せで使用される索引と、問合せにプッシュ・ダウンされた条件を確認する必要があります。この情報を基に、索引ヒントを介して別の索引の使用を強制する場合があります。この情報は、問合せ実行計画に含まれます。すべてのOracle NoSQLドライバに、問合せの実行計画を表示するAPIが用意されています。IntelliJ、VSCode、Eclipseプラグインを含むすべてのOracle NoSQLグラフィカルUIと、Oracle Cloud Infrastructureコンソールには、問合せ実行計画を表示するためのコントロールが含まれています。

問合せで使用される最も一般的で重要なイテレータの一部を次に示します。

TABLEイテレータ

表イテレータは次のことを行います
  • 問合せで使用される索引のスキャン(主索引の場合もあります)。
  • 索引にプッシュされるフィルタリング条件の適用
  • 必要に応じて、条件を満たす索引エントリが指す行を取得します。カバー索引の場合、TABLEイテレータの結果セットは索引エントリのセットであり、それ以外の場合は表の行のセットです。

ノート:

索引は、その索引のエントリのみを使用して問合せを評価できる場合、つまり、関連付けられた行を取得する必要がない場合、問合せに関するカバー索引と呼ばれます。
TABLEイテレータには、常に次のプロパティがあります。
  • target table: 問合せのターゲット表の名前。
  • index used: 問合せで使用される索引の名前。主索引が使用された場合、このプロパティの値として"primary index"が示されます。
  • covering index: カバー索引かどうか。
  • row variable: TABLEイテレータによって生成された表の行全体にわたる変数の名前。カバー索引の場合、表の行は生成されず、この変数は使用されません。
  • index scans: 実行する索引スキャンを定義する開始条件と停止条件が含まれます。
TABLEイテレータには、さらに2つのオプション・プロパティがあります。
  • index row variable: TABLEイテレータによって生成された索引エントリ全体にわたる変数の名前。新しい索引エントリが索引スキャンによって生成されるたびに、索引変数がそのエントリにバインドされます。
  • index filtering predicate: 索引スキャンによって生成されるすべての索引エントリで評価される条件。この評価の結果がtrueの場合、索引変数はこのエントリにバインドされ、TABLEイテレータに対するnext()コールの結果として、エントリまたは関連する表の行が返されます。それ以外の場合、エントリはスキップされ、索引スキャンからの次のエントリが生成されます。このエントリで条件が再度評価され、条件を満たすエントリが見つかるまで続行されます。

SELECTイテレータ

SELECT式を実行します。

RECEIVEイテレータ

問合せ計画を2つの部分に分ける特別な内部イテレータです。
  1. RECEIVEイテレータ自体と、イテレータ・ツリー内でその上にあるすべてのイテレータがドライバで実行されます。
  2. RECEIVEイテレータの下にあるすべてのイテレータは、レプリケーション・ノード(RN)で実行されます。これらのイテレータは、RECEIVEイテレータの一意の子をルートとするサブツリーを形成します。

通常、RECEIVEイテレータは問合せコーディネータとして機能します。実行のためにサブプランを適切なRNに送信し、結果を収集します。ソートや重複削除などの追加操作を実行し、その結果をその祖先イテレータ(存在する場合)に伝播して、さらに処理できます。

分散の種類

distribution kindは、Oracle NoSQLデータベース(ストア)に参加しているRN間で問合せを分散して実行する方法を指定します。distribution kindは、RECEIVEイテレータのプロパティです。

分散の種類には次の選択肢があります。
  • SINGLE_PARTITION: SINGLE_PARTITION問合せでは、WHERE句に完全なシャード・キーを指定します。その結果、結果セット全体が単一のパーティションに含まれ、RECEIVEイテレータはそのパーティションを格納する単一のRNにサブプランを送信します。SINGLE_PARTITION問合せでは、主キー索引または2次索引のいずれかを使用できます。
  • ALL_PARTITIONS: 問合せでは、ここで主キー索引を使用し、完全なシャード・キーは指定しません。その結果、ストアにM個のパーティションがある場合、RECEIVEイテレータはそのサブプランのコピーをM個送信して、それぞれがM個のパーティションのいずれかで実行されるようにします。
  • ALL_SHARDS: 問合せでは、ここで2次索引を使用し、完全なシャード・キーは指定しません。その結果、ストアにN個のシャードがある場合、RECEIVEイテレータはそのサブプランのコピーをN個送信して、それぞれがN個のシャードのいずれかで実行されるようにします。

問合せ実行計画を確認するための表へのデータ移入:

例のとおりに操作する場合は、スクリプトbaggageschema_loaddata.sqlをダウンロードして、次に示すように実行します。このスクリプトにより、例で使用する表が作成され、表にデータがロードされます。

KVSTOREまたはKVLiteを起動し、SQL.shellを開きます。
java -jar lib/kvstore.jar kvlite -secure-config disable
java -jar lib/sql.jar -helper-hosts localhost:5000 -store kvstore
loadコマンドを使用して、スクリプトを実行します。
load -file baggageschema_loaddata.sql

索引の作成:

次に示すように、baggageInfo表に次の索引を作成します。
  1. 乗客予約コードに対する索引を作成します。
    CREATE INDEX fixedschema_conf ON baggageInfo confNo)
  2. 乗客のフルネームと電話番号に対する索引を作成します
    CREATE INDEX compindex_namephone ON baggageInfo (fullName,contactPhone)
  3. 手荷物が最後に確認された日時、最後に確認されたステーションおよび到着日時という3つのフィールドに対する索引を作成します。
    CREATE INDEX simpleindex_arrival ON 
    baggageInfo(bagInfo[].lastSeenTimeGmt as ANYATOMIC,
    bagInfo[].bagArrivalDate as ANYATOMIC, 
    bagInfo[].lastSeenTimeStation as ANYATOMIC)