ユーザーコマンドの各サブコマンドに対して、適切なサブプランナーが使用されます(リレーショナル、XML、プロシージャなど)。
各プランナーには3つの主要フェーズがあります:
- カノニカルプランの生成
- 最適化
- 計画からプロセスへの変換 - 計画データ構造を処理形式に変換します。
Relational Planner
一連の規則が論理計画を操作した後、Optimizationは関係処理計画を作成します。ルールの適用は、Query Structureとルール自体によって決定されます。デバッグ計画のノード構造は処理計画と似ていますが、ノード型はより論理的にSQL操作を表しています。
Canonical Plan and All Nodes
書き換え後のUser SQL文は、正規プラン形式に変換されます。正規プランの形式は、SQLの初期構造に最もよく似ています。SQLのselectクエリには次のような句があります(SELECT
以外はすべてオプションです):WITH
SELECT
, , , , , , . FROM
WHERE
GROUP BY
HAVING
ORDER BY
LIMIT
これらの句は、論理的には以下の順序で実行されます:
WITH
(共通テーブル式の作成) - 専用化されたPROJECT NODE
FROM
(テーブルからすべてのデータを読み込んで結合) -FROM
句項目ごとにSOURCE
ノード、JOIN
ノード (テーブルが 1 つ以上ある場合)WHERE
(filter rows) - ノードSELECT
GROUP BY
(行を折りたたまれた行にグループ化) - ノードGROUP
HAVING
(グループ化された行をフィルタリング) - ノードSELECT
SELECT
(式を評価し、要求された行のみを返す) -PROJECT
ノードとDUP_REMOVE
ノード (SELECT DISTINCT
の場合)INTO
- specializedPROJECT
with aSOURCE
childORDER BY
(行の並べ替え) -SORT
ノード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])
Source
はFROM
句に対応し、Select
はWHERE
句に対応し、Group
は最大集約を作成するための暗黙のグループ化に対応し、Project
はSELECT
句に対応します。
グループ化の効果は、グループ化によって作成された値の投影を処理するために、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 |
---|---|
| Final form of a source request |
| Metadata object for the target schema |
| Used in planning procedural relational queries |
| Set to |
| Used to track the multi-source source name |
| Tracks the set of conformed sources when the conformed extension metadata is used |
| Used in multi-source planning |
Set Operation Properties
Property Name | Description |
---|---|
| Defines the set operation ( |
Join Properties
Property Name | Description |
---|---|
| All join predicates |
| Type of join ( |
| Algorithm to use (nested loop, merge, etc.) |
| Expressions in equi-join predicates that originate from the left side of the join |
| Expressions in equi-join predicates that originate from the right side of the join |
| Set if a dependent join is used |
| Non-equi join predicates |
| Indicates if the left side needs sorting for join processing |
| Indicates if the right side needs sorting for join processing |
| Indicates if the join is optional |
| Indicates if the left side is distinct with respect to the equi join predicates |
| Indicates if the right side is distinct with respect to the equi join predicates |
| Indicates if the dependent join represents a semi-join |
| Indicates if the preserve hint is preserving the join order |
Project Properties
Property Name | Description |
---|---|
| Expressions projected |
| Group targeted if this is a select into or insert with a query expression |
|
|
| Constraint that must be met if the values are being projected into a group |
Select Properties
Property Name | Description |
---|---|
| Filter |
| Indicates if the filter is applied after grouping |
|
|
| Inferred criteria that may not be used in the final plan |
| Indicates if rule copy criteria have already processed the criteria |
| Indicates if the criteria are pushed as far as possible |
| Indicates if the criteria are the filter of a dependent join |
Sort Properties
Property Name | Description |
---|---|
| Order by that defines the sort |
| Indicates if the ordering includes a value that is not being projected |
| Indicates if the sort should also perform duplicate removal over the entire projection |
Source Properties
Property Name | Description |
---|---|
| Mapping from the columns above the source to the projected expressions. Also present on Group nodes |
| Partitioning of the union branches |
| Indicates if the source represents a view or inline view, the query that defined the view |
| Hint information |
| Processor plan of a non-relational source (typically from |
| Non-relational command |
| Table function ( |
| Correlated references for the nodes below the source |
| Indicates if |
| Indicates if the source node represents an inline view |
| Indicates if the |
| Source hint |
| Access patterns yet to be satisfied |
| Satisfied access patterns |
| 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 |
---|---|
| Grouping columns |
Tuple Limit Properties
Property Name | Description |
---|---|
| Expression that evaluates the max number of tuples generated |
| Expression that evaluates the tuple offset of the starting tuple |
| Indicates if the rewriter creates the limit as part of a subquery optimization |
| Indicates if the unordered limit should not be enforced strictly |
General and Costing Properties
Property Name | Description |
---|---|
| Output columns for the node. Typically set after rule assign output elements. |
| Represents the estimated set size this node would produce for a sibling node as the independent node in a dependent join scenario |
| Represents the estimated cardinality (amount of rows) produced by this node as the dependent node in a dependent join scenario |
| Represents the estimated cost of a dependent join (the join strategy for this could be Nested Loop or Merge) |
| Represents the estimated cost of a merge join (the join strategy for this could be Nested Loop or Merge) |
| Represents the estimated cardinality (amount of rows) produced by this node |
| Column statistics, including the number of null values, distinct value count, etc. |
| 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から取得するデータを大幅に削減できるため、クエリ全体の速度を大幅に向上させることができます。
- JOINは以下の場合にDependentとなります:
- 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値を導入する可能性があるためです。
- Criteriaのプッシュに関連する最も重要なOptimizationの1つは、Criteriaがどのように結合を通してプッシュされるかです。
- レイズ・アクセス - このルールは、アクセスノードを可能な限りプランの上方に上げようとします。これは主にソースの能力を調べ、そのソースでオペレーションが実現できるかどうかを判断することで行われます。
- 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プログラムは再帰的であることもできます。これは、ある終了基準または制限が満たされるまで、最初のフラグメントと繰り返されるフラグメントのセット(それぞれが新しいクエリ)の両方に同じドキュメントフラグメントを使用することを含みます。