ユーザーコマンドの各サブコマンドに対して、適切なサブプランナーが使用されます(リレーショナル、XML、プロシージャなど)。

各プランナーには3つの主要フェーズがあります:

  1. カノニカルプランの生成
  2. 最適化
  3. 計画からプロセスへの変換 - 計画データ構造を処理形式に変換します。

Relational Planner

一連の規則が論理計画を操作した後、Optimizationは関係処理計画を作成します。ルールの適用は、Query Structureとルール自体によって決定されます。デバッグ計画のノード構造は処理計画と似ていますが、ノード型はより論理的にSQL操作を表しています。

Canonical Plan and All Nodes

書き換え後のUser SQL文は、正規プラン形式に変換されます。正規プランの形式は、SQLの初期構造に最もよく似ています。SQLのselectクエリには次のような句があります(SELECT以外はすべてオプションです):WITHSELECT , , , , , , . FROMWHEREGROUP BYHAVINGORDER BYLIMITこれらの句は、論理的には以下の順序で実行されます:

  1. WITH (共通テーブル式の作成) - 専用化されたPROJECT NODE
  2. FROM (テーブルからすべてのデータを読み込んで結合) - FROM 句項目ごとにSOURCE ノード、JOIN ノード (テーブルが 1 つ以上ある場合)
  3. WHERE (filter rows) - ノードSELECT
  4. GROUP BY (行を折りたたまれた行にグループ化) - ノードGROUP
  5. HAVING (グループ化された行をフィルタリング) - ノードSELECT
  6. SELECT (式を評価し、要求された行のみを返す) - PROJECT ノードとDUP_REMOVE ノード (SELECT DISTINCT の場合)
  7. INTO - specialized PROJECT with a SOURCE child
  8. ORDER BY (行の並べ替え) - SORT ノード
  9. LIMIT (結果セットを特定の範囲に制限する) - LIMIT ノード

例えば、SELECT max(g1.e1) FROM g1 WHERE e2 = 1 のようなSQL文は論理計画を作成します:

Project(groups=[anon_grp0], props={PROJECT_COLS=[anon_grp0.agg0 AS expr1]})
Group(groups=[anon_grp0], props={SYMBOL_MAP={anon_grp0.agg0=MAX(g1.e1)}})
Select(groups=[g1], props={SELECT_CRITERIA=e2 = 1})
Source(groups=[g1])

SourceFROM 句に対応し、SelectWHERE 句に対応し、Group は最大集約を作成するための暗黙のグループ化に対応し、ProjectSELECT 句に対応します。

グループ化の効果は、グループ化によって作成された値の投影を処理するために、anon_grp0という事実上インラインビューを生成することに注意してください。

All Node Types

  • ACCESS - ソースアクセスまたはプラン実行

  • DUP_REMOVE - 重複行の削除

  • JOIN - join (LEFT OUTER, FULL OUTER, INNER, CROSS, SEMI, etc.)

  • PROJECT - タプル値の投影

  • SELECT - タプルのフィルタリング

  • SORT - 順序付け操作は、結合などの他の操作を処理するために挿入されることがあります。

  • SOURCE - インライン・ビュー、ソース・アクセス、XMLTABLE など、あらゆる論理的なタプルのソース。

  • GROUP - grouping オペレーション

  • SET_OP - set オペレーション (UNION/INTERSECT/EXCEPT)

  • NULL - タプルのないソース

  • TUPLE_LIMIT - 行オフセット / リミット

Node Properties

各ノードには、通常ノード上に表示される適用可能なプロパティのセットがあります。

Access Properties

Property Name

Description

ATOMIC_REQUEST

Final form of a source request

MODEL_ID

Metadata object for the target schema

PROCEDURE_CRITERIA/PROCEDURE_INPUTS/PROCEDURE_DEFAULTS

Used in planning procedural relational queries

IS_MULTI_SOURCE

Set to TRUE when the node represents a multi-source access

SOURCE_NAME

Used to track the multi-source source name

CONFORMED_SOURCES

Tracks the set of conformed sources when the conformed extension metadata is used

SUB_PLAN/SUB_PLANS

Used in multi-source planning

Set Operation Properties

Property Name

Description

SET_OPERATION/USE_ALL

Defines the set operation (UNION/INTERSECT/EXCEPT) and if all rows or distinct rows are used.

Join Properties

Property Name

Description

JOIN_CRITERIA

All join predicates

JOIN_TYPE

Type of join (INNER, LEFT OUTER, etc.)

JOIN_STRATEGY

Algorithm to use (nested loop, merge, etc.)

LEFT_EXPRESSIONS

Expressions in equi-join predicates that originate from the left side of the join

RIGHT_EXPRESSIONS

Expressions in equi-join predicates that originate from the right side of the join

DEPENDENT_VALUE_SOURCE

Set if a dependent join is used

NON_EQUI_JOIN_CRITERIA

Non-equi join predicates

SORT_LEFT

Indicates if the left side needs sorting for join processing

SORT_RIGHT

Indicates if the right side needs sorting for join processing

IS_OPTIONAL

Indicates if the join is optional

IS_LEFT_DISTINCT

Indicates if the left side is distinct with respect to the equi join predicates

IS_RIGHT_DISTINCT

Indicates if the right side is distinct with respect to the equi join predicates

IS_SEMI_DEP

Indicates if the dependent join represents a semi-join

PRESERVE

Indicates if the preserve hint is preserving the join order

Project Properties

Property Name

Description

PROJECT_COLS

Expressions projected

INTO_GROUP

Group targeted if this is a select into or insert with a query expression

HAS_WINDOW_FUNCTIONS

TRUE if window functions are used

CONSTRAINT

Constraint that must be met if the values are being projected into a group

Select Properties

Property Name

Description

SELECT_CRITERIA

Filter

IS_HAVING

Indicates if the filter is applied after grouping

IS_PHANTOM

TRUE if the node is marked for removal, but temporarily left in the plan

IS_TEMPORARY

Inferred criteria that may not be used in the final plan

IS_COPIED

Indicates if rule copy criteria have already processed the criteria

IS_PUSHED

Indicates if the criteria are pushed as far as possible

IS_DEPENDENT_SET

Indicates if the criteria are the filter of a dependent join

Sort Properties

Property Name

Description

SORT_ORDER

Order by that defines the sort

UNRELATED_SORT

Indicates if the ordering includes a value that is not being projected

IS_DUP_REMOVAL

Indicates if the sort should also perform duplicate removal over the entire projection

Source Properties

Property Name

Description

SYMBOL_MAP

Mapping from the columns above the source to the projected expressions. Also present on Group nodes

PARTITION_INFO

Partitioning of the union branches

VIRTUAL_COMMAND

Indicates if the source represents a view or inline view, the query that defined the view

MAKE_DEP

Hint information

PROCESSOR_PLAN

Processor plan of a non-relational source (typically from NESTED_COMMAND)

NESTED_COMMAND

Non-relational command

TABLE_FUNCTION

Table function (XMLTABLE, OBJECTTABLE, etc.) defining the source

CORRELATED_REFERENCES

Correlated references for the nodes below the source

MAKE_NOT_DEP

Indicates if MAKE_NOT_DEP is set

INLINE_VIEW

Indicates if the source node represents an inline view

NO_UNNEST

Indicates if the NO_UNNEST hint is set

SOURCE_HINT

Source hint

ACCESS_PATTERNS

Access patterns yet to be satisfied

ACCESS_PATTERN_USED

Satisfied access patterns

REQUIRED_ACCESS_PATTERN_GROUPS

Groups needed to satisfy the access patterns. Used in join planning.

Many source properties also become present on associated access nodes.


Group Properties

Property Name

Description

GROUP_COLS

Grouping columns 

Tuple Limit Properties

Property Name

Description

MAX_TUPLE_LIMIT

Expression that evaluates the max number of tuples generated

OFFSET_TUPLE_COUNT

Expression that evaluates the tuple offset of the starting tuple

IS_IMPLICIT_LIMIT

Indicates if the rewriter creates the limit as part of a subquery optimization

IS_NON_STRICT

Indicates if the unordered limit should not be enforced strictly

General and Costing Properties

Property Name

Description

OUTPUT_COLS

Output columns for the node. Typically set after rule assign output elements.

EST_SET_SIZE

Represents the estimated set size this node would produce for a sibling node as the independent node in a dependent join scenario

EST_DEP_CARDINALITY

Represents the estimated cardinality (amount of rows) produced by this node as the dependent node in a dependent join scenario

EST_DEP_JOIN_COST

Represents the estimated cost of a dependent join (the join strategy for this could be Nested Loop or Merge)

EST_JOIN_COST

Represents the estimated cost of a merge join (the join strategy for this could be Nested Loop or Merge)

EST_CARDINALITY

Represents the estimated cardinality (amount of rows) produced by this node

EST_COL_STATS

Column statistics, including the number of null values, distinct value count, etc.

EST_SELECTIVITY

Represents the selectivity of a criteria node

Rules

リレーショナル最適化は、初期計画を実行計画に進化させるルール実行に基づいています。事前に定義されたルールのセットは、すべてのクエリのルールスタックに動的に組み立てられます。ルールスタックは、ユーザーのクエリの内容とアクセスされたビュー / プロシージャに基づいて組み立てられます。例えば、ビューレイヤーがない場合、ビューレイヤーをマージするルールMerge Virtual は不要であり、スタックに追加されません。これにより、クエリの複雑さをルールスタックに反映させることができます。

論理的には、プランノードのデータ構造はノードのツリーを表し、ソースデータはリーフノード(通常、最終プランのAccessノード)から上がってきて、ツリー内を流れ、最上部からユーザーの結果を生成します。プラン構造のノードは、双方向リンクと動的プロパティを持つことができ、任意の数の子ノードを持つことができます。対照的に、処理計画は、通常、固定されたプロパティを持っています。

プランルールはプランツリーを操作し、他のルールを起動し、Optimizationプロセスを推進します。各ルールは狭い範囲のタスクを実行するように設計されています。ルールによっては複数回実行できるものもあります。ルールの中には、正しく実行するために特定の前駆体セットを必要とするものがあります。

  • アクセスパターンの検証 - すべてのアクセスパターンが満たされていることを確認します。
  • Apply Security - 行および列レベルのセキュリティを適用します。
  • Assign Output Symbol - このルールはすべてのノードをトップダウンで走査し、各ノードの出力列を計算します。不要な列は各ノードで削除され、これは射影最小化として知られています。これは、親ノードへのフィードに必要な列と、特定のノードで「作成」された列の両方を追跡することによって行われます。
  • コスト計算 - プランにコスト情報を追加します。
  • Dependent の選択 - このルールは、各 join ノードを調べ、その join を依存にするかどうか、またその方向を決定します。カーディナリティ、異なる値の数、プライマリキー情報は、従属joinが価値があるかどうかを判断するために、いくつかの計算式で使用されます。Dependent Join では、従属側から返される値の数が少なくなるため、理想的にはパフォーマンスが異なります。また、独立側から従属側に渡されるVALUの数も考慮しなければなりません。その設定が、従属側のINTO条件における値の最大数よりも大きい場合、クエリをクエリのセットに分割し、その結果を組み合わせる必要があります。コネクタ内の各クエリの実行にはオーバーヘッドがあり、それは考慮されています。原価計算情報がないと、指定されたCriteriaが一意でない(しかし強く制限される)フィールドのみである多くの一般的なケースを見逃してしまいます。
    • JOINは以下の場合にDependentとなります:
      • すなわち、table_a.col = table_b.col。
      • joinが完全な外部joinではなく、joinの従属側がjoinの内側にある場合。
    • 優先順位順に列挙された以下の条件のいずれかが成立する場合、JoinはDependentになります:
      • Dependent Joinクライテリアで満たすことができる、満たされていないアクセスパターンがあります。
      • JOINの潜在的な依存側には、オプションが付けられています。MAKEDEP
      • キーメタデータ情報が、潜在的従属側が "small "ではなく、もう一方が "not small "または(5.0.1)であることを示す場合、潜在的従属側は左外側結合の内側となります。
    • Dependent Joinは、マルチソースJoinを効率的に処理するための重要な最適化です。ソースAとソースBをすべて読み込んでA.x = B.xで結合するのではなく、Aをすべて読み込んでからA.xのセットを作成し、Bにクエリを実行する際の条件として渡します。 Aが小さくBが大きい場合、Bから取得するデータを大幅に削減できるため、クエリ全体の速度を大幅に向上させることができます。
  • Choose Join Strategy(参加戦略の選択) - 参加のコストと属性に基づいて参加戦略を選択します。
  • Clean Criteria - 幻のCriteriaを削除します。
  • ソースの折りたたみ - アクセス・ノード以下のすべてのノードを取り込み、SQL クエリ表現を作成します。
  • Copy Criteria - このルールは、結合のクライテリアに存在する等しいクライテリアの上にクライテリアをコピーします。等式は等価性を定義するので、これは結合の反対側で結果を制限する可能性のある新しいCriteriaを作成する有効な方法です(特に複数ソース結合の場合)。
  • Decompose Join - このルールは、Federated Optimizations#Partitioned Unionジョインに対してパーティションごとのジョイン最適化を実行します。分解の決定は、結合の各側がパーティショニングされた結合であることを検出することに基づいています(2つ以上のテーブルの非ANSI結合は、Optimizationが適切な結合を検出しない可能性があることに注意してください)。このルールは現在、各サイドから最大1つのパーティションが一致する状況のみを探します。
  • Joinストラテジーの実装 - 選択したJoinストラテジーを処理するために必要なソートやその他のノードを追加します。
  • Merge Criteria - select ノードを結合し、Subqueries をSemi-Join に変換します。
  • Merge Virtual - View とInline View のレイヤーを削除します。
  • Place Access - アクセスノードをソースノードの下に配置します。アクセスノードは、アクセスノード以下のすべてのものがソースにプッシュされる、あるいはプランの呼び出しとなるポイントを表します。LATERALルールは、アクセスノードをツリーの下へ押し出すか、ツリーの上へ引っ張り、より多くの作業をソースへ移動させることに重点を置いています。このルールは Federated Optimizations#Access Patternsを配置する役割も担っています。
  • Plan Joins - このルールは、 Federated Optimizations#Access Patterns の依存関係が満たされるようにしながら、プランで実行される結合の最適な順序を見つけようとします。このルールには主に3つのステップがあります。まず、現在のアクセスパターンを満たす結合の順序を決定する必要があります。次に、ソースにプッシュできる結合を発見的に作成します(結合のセットがソースにプッシュされる場合、そのセット内でOptimizationsを作成しようとはしません)。おそらく、ANSIではないマルチジョイン構文でソースに送信され、データベースによって最適化されるでしょう)。第三に、コスト情報を使用して、処理エンジンで実行される結合の最適な左線形順序を決定します。この第3のステップは、7つ以下の結合ソースに対しては網羅的検索を行い、8つ以上のソースに対しては結合選択性によってヒューリスティックに駆動されます。
  • Plan OUTER JOIN - 外側結合の順序を変更し、プッシュダウンを改善します。
  • Plan Procedures - プロシージャ型リレーショナルクエリに表示されるプロシージャを計画します。
  • ソート計画 - ソート操作の組み合わせや投影の移動など、ソートに関する Optimizations。
  • プラン・ユニオン - ユニオン・チャイルドを並べ替え、Pushdownを強化。
  • Plan Aggregates(プラン・アグリゲート) - JOINまたはUNIONに対して集約分解を実行します。
  • Push Limit - リミットノードの効果をさらにプランに押し込みます。
  • Push Non-Join Criteria - このルールは、結合の正しさのために必要でない場合、on 句から述語を押し出します。
  • SELECT Criteria(SELECT基準のプッシュ) - ユニオン、JOIN、およびViewレイヤーを通して、アクセス・ノードに向かって可能な限りSELECTノードをプッシュします。たいていの場合、ツリーを下に移動することは、プランの早い段階で行をフィルタリングすることになり、良いことです。現在のところ、Push Select Criteriaによる決定を取り消すことはできません。しかし、SourcesがCriteriaを評価できない場合、これは最適でない計画につながる可能性があります。
    • Criteriaのプッシュに関連する最も重要なOptimizationの1つは、Criteriaがどのように結合を通してプッシュされるかです。
      • 以下の計画木を考えてみましょう。"select ... from A inner join b on (A.x = B.x) where A.y = 3 "というクエリの計画の部分木です。 

        • (SELECTノードはCriteriaを表し、SRCはSOURCEを表します)。

          SELECT (B.y = 3)
           |
          JOIN (Inner Join on (A.x = B.x))
          /        \  
          SRC(A)   SRC(B)

        • 内側joinと交差joinでは、(単一ソースの)Criteriaを上下にプッシュすることは常に有効です。
          この結果は、視覚的に次のように表すことができます:

          JOIN (Inner Join on (A.x = B.x))
             /     \
            /     SELECT (B.y = 3)
           |        |
          SRC(A)   SRC(B)

      • 外側joinの外側に対して指定されたCriteriaに対しても同じ最適化が有効です。

        • 例えば

          SELECT (B.y = 3)
           |
          JOIN (Right Outer Join on (A.x = B.x))
          /        \  
          SRC(A)   SRC(B)

          になります。

          JOIN  (Right Outer Join on (A.x = B.x))
             /      \
            /     SELECT (B.y = 3)
           |         |
          SRC(A)    SRC(B)

      • しかし、外側結合の内側に対して指定されたCriteriaは特別な考慮が必要です。左外部結合または完全外部結合での上記のシナリオは異なります。

        • 例えば

          SELECT (B.y = 3)
           |
          JOIN (Left Outer Join on (A.x = B.x))
           /     \  
          SRC(A) SRC(B)

          になることができます。

          JOIN (Inner Join on (A.x = B.x))
            /  \
           / SELECT (B.y = 3)
          |       |
          SRC(A) SRC(B)

          → 基準は結合の内側から入力されるNULL値には依存しないので、基準は結合の下にプッシュすることができます。

      • 一方、NULL値の存在に依存するCriteriaは移動できません。
        • 例えば

          SELECT (B.y is null)
           |
          JOIN (Left Outer Join on (A.x = B.x))
           /     \
          SRC(A) SRC(B)

          → 外側join自体がNULL値を導入する可能性があるためです。

  • レイズ・アクセス - このルールは、アクセスノードを可能な限りプランの上方に上げようとします。これは主にソースの能力を調べ、そのソースでオペレーションが実現できるかどうかを判断することで行われます。
  • Raise NULL - NULL ノードを発生させます。NULLノードを上げると、NULLノードより下のOLDプランの部分を考慮する必要がなくなります。
  • Remove Optional Joins - オプションとしてマークされた、またはオプションであると判断された結合を削除します。
  • Substitute Expressions - 関数ベースのインデックスが存在する場合にのみ使用されます。
  • Validate Where All - Sources で必要なときに Criteria が使用されるようにします。

Reading a Debug Plan

各関係サブプランが最適化されると、プランには最適化されているものとその正規形が表示されます:

OPTIMIZE:
SELECT e1 FROM (SELECT e1 FROM t1.g1) AS x
 
----------------------------------------------------------------------------
GENERATE CANONICAL:
SELECT e1 FROM (SELECT e1 FROM t1.g1) AS x
 
CANONICAL PLAN:
Project(groups=[x], props={PROJECT_COLS=[e1]})
Source(groups=[x], props={NESTED_COMMAND=SELECT e1 FROM t1.g1, SYMBOL_MAP={x.e1=e1}})
Project(groups=[t1.g1], props={PROJECT_COLS=[e1]})
Source(groups=[t1.g1])


プロシージャ呼び出しやサブクエリを含むような、より複雑なUser Queryでは、サブ計画は全体計画の中に入れ子にされるかもしれません。各プランは、最終的な処理計画を示して終了します:

----------------------------------------------------------------------------
OPTIMIZATION COMPLETE:
PROCESSOR PLAN:
AccessNode(0) output=[e1] SELECT g_0.e1 FROM t1.g1 AS g_0


ルールの効果は、ルール発火前後のプランツリーの状態によって確認できます。例えば、以下のデバッグログは、"x "インラインビューレイヤーを削除するルールmerge virtual の適用を示しています:

EXECUTING AssignOutputElements
 
AFTER:
Project(groups=[x], props={PROJECT_COLS=[e1], OUTPUT_COLS=[e1]})
Source(groups=[x], props={NESTED_COMMAND=SELECT e1 FROM t1.g1, SYMBOL_MAP={x.e1=e1}, OUTPUT_COLS=[e1]})
Project(groups=[t1.g1], props={PROJECT_COLS=[e1], OUTPUT_COLS=[e1]})
Access(groups=[t1.g1], props={SOURCE_HINT=null, MODEL_ID=Schema name=t1, nameInSource=null, uuid=3335, OUTPUT_COLS=[e1]})
Source(groups=[t1.g1], props={OUTPUT_COLS=[e1]})
 
 
============================================================================
EXECUTING MergeVirtual
 
AFTER:
Project(groups=[t1.g1], props={PROJECT_COLS=[e1], OUTPUT_COLS=[e1]})
Access(groups=[t1.g1], props={SOURCE_HINT=null, MODEL_ID=Schema name=t1, nameInSource=null, uuid=3335, OUTPUT_COLS=[e1]})
Source(groups=[t1.g1])


重要なプランニングの決定事項は、その都度注釈としてプランに表示されます。例えば、以下のスニペットは、親 select ノードにサポートされていない Subquery が含まれていたため、アクセス・ノードを上げることができなかったことを示しています。

Project(groups=[t1.g1], props={PROJECT_COLS=[e1], OUTPUT_COLS=null})
Select(groups=[t1.g1], props={SELECT_CRITERIA=e1 IN /*+ NO_UNNEST */ (SELECT e1 FROM t2.g1), OUTPUT_COLS=null})
Access(groups=[t1.g1], props={SOURCE_HINT=null, MODEL_ID=Schema name=t1, nameInSource=null, uuid=3341, OUTPUT_COLS=null})
Source(groups=[t1.g1], props={OUTPUT_COLS=null})
 
 
============================================================================
EXECUTING RaiseAccess
LOW Relational Planner SubqueryIn is not supported by source t1 - e1 IN /*+ NO_UNNEST */ (SELECT e1 FROM t2.g1) was not pushed
 
AFTER:
Project(groups=[t1.g1])
Select(groups=[t1.g1], props={SELECT_CRITERIA=e1 IN /*+ NO_UNNEST */ (SELECT e1 FROM t2.g1), OUTPUT_COLS=null})
Access(groups=[t1.g1], props={SOURCE_HINT=null, MODEL_ID=Schema name=t1, nameInSource=null, uuid=3341, OUTPUT_COLS=null})
Source(groups=[t1.g1])


Procedure Planner

プロシージャプランナーはいたってシンプルです。これは、プロシージャ内のステートメントを、処理中に実行されるプログラムの命令に変換します。これは主に1対1のマッピングであり、最小限の Optimization が実行されます。

XML Planner

XML Planner は、Procedure Planner の最終結果に比較的近いXML計画、つまり、命令を持つプログラムを作成します。多くの命令は似ています(whileループ、SQLの実行など)。追加命令には、出力結果文書の作成(要素と属性の追加)が含まれます。

XMLプランナーはいくつかのタイプのプランニングを行います(必ずしもこの順序ではありません):

  • 文書選択 - 仮想文書のどのタグを出力文書から除外するかを決定します。これは、モデル(ドキュメントの一部を除外する)とクエリ(SELECT句に含めるカラムのサブセットを指定する)の組み合わせに基づいて行われます。
  • Criteria評価 - UserのCriteriaを分解し、Criteriaがどの結果セットに適用されるべきかを決定し、その結果セットクエリにそのCriteriaを追加します。
  • 結果セットの順序付け - クエリの ORDER BY 句は分割され、必要に応じて ORDER BY が各結果セットに適用されます。
  • 結果セットの計画 - 最終的に、各結果セットはリレーショナルプランナを使用し、UserのQueryからのすべての影響を考慮して計画されます。プランナはまた、マッピングクラス階層に基づいてステージングテーブルと依存Joinを自動的に作成するようにします。
  • プログラム生成 - 最終的な結果セットのクエリや文書の除外部分を考慮して、希望する出力文書を作成するための命令セットが作成されます。一般的には、ドキュメント順に仮想ドキュメントを走査し、必要に応じてクエリを実行し、要素や属性を出力します。

XMLプログラムは再帰的であることもできます。これは、ある終了基準または制限が満たされるまで、最初のフラグメントと繰り返されるフラグメントのセット(それぞれが新しいクエリ)の両方に同じドキュメントフラグメントを使用することを含みます。