19 オプティマイザへの影響
オプティマイザのデフォルト設定は、ほとんどの操作に適しています(すべてではありません)。
オプティマイザにとって不明な情報が含まれている場合や、特定の種類の文またはワークロードにオプティマイザを合せる必要がある場合もあります。そのような場合は、オプティマイザに与える影響によりパフォーマンスを改善できることがあります。
19.1 オプティマイザに影響を与える手法
SQLプロファイル、SQL計画管理、初期化パラメータおよびヒントなど、様々な手法を使用してオプティマイザに影響を与えることができます。
次の図は、オプティマイザに影響を与える主要な手法を示しています。
前述の図にある重なり合った四角形は、SQL計画管理が初期化パラメータとヒントの両方を使用していることを示しています。また、SQLプロファイルにも技術的にはヒントが含まれています。
ノート:
ストアド・アウトラインは、SQL計画ベースラインとよく似た目的を果たすレガシーな手法です。
次の手法を使用してオプティマイザに影響を与えることができます。
表19-1 オプティマイザの手法
手法 | 説明 | さらに学習するには |
---|---|---|
初期化パラメータ |
パラメータは、オプティマイザの多くの種類の動作にデータベース・インスタンスやセッション・レベルで影響を与えます。 |
|
ヒント |
ヒントは、SQL文でコメント化された命令です。ヒントで広範囲の動作が制御されます。 |
|
|
このパッケージではオプティマイザ統計を更新および管理します。統計をより正確にすることで、オプティマイザの見積りもより改善されます。この章では、 |
|
SQLプロファイル |
SQLプロファイルは、SQL文に固有の補足統計を含むデータベース・オブジェクトです。概念上、SQL文に対するSQLプロファイルの役割は、表または索引に対するオブジェクト・レベルの統計情報の役割と同じです。SQLプロファイルにより、SQLチューニングの間に見つかった最適ではないオプティマイザの見積りを修正できます。 |
|
SQL計画管理とストアド・アウトライン |
SQL計画管理は、データベースで既知の計画または確認済の計画のみが使用されるようにオプティマイザで実行計画を自動的に管理する予防的なメカニズムです。この章では、SQL計画管理については扱いません。 |
場合によっては、複数の手法で同じ動作を最適化します。たとえば、初期化パラメータとヒントの両方を使用してオプティマイザの目標を設定できます。
関連項目:
ストアド・アウトラインをSQL計画ベースラインに移行する方法を学習するには、「ストアド・アウトラインのSQL計画ベースラインへの移行」を参照してください
19.2 初期化パラメータによるオプティマイザへの影響
この章では、最適化に影響を与える初期化パラメータと、その設定方法について説明しています。
19.2.1 オプティマイザの初期化パラメータについて
Oracle Databaseには、カーソル共有、適応最適化およびオプティマイザ・モードを含めてオプティマイザ動作の様々な面に影響を与える初期化パラメータが提供されています。
次の表に、最も重要なオプティマイザ・パラメータの一部を示します。この表には、近似問合せ初期化パラメータが含まれていないことに注意してください。近似問合せの初期化パラメータで説明しています。
表19-2 オプティマイザ動作を制御する初期化パラメータ
初期化パラメータ | 説明 |
---|---|
CURSOR_INVALIDATION |
DDL文のデフォルトのカーソル無効化レベルを指定します。
このパラメータは、 |
|
SQL文のリテラル値をバインド変数に変換します。値を変換するとカーソル共有が改善され、SQL文の実行計画は影響を受けます。オプティマイザは、実際のリテラル値でなくバインド変数の有無に基づいて実行計画を生成します。
|
|
全表スキャンまたは高速全索引スキャン時に単一I/Oで読み取られるブロックの個数を指定します。オプティマイザは、このパラメータの値を使用して、全表スキャンと高速全索引スキャンのコストを計算します。値が大きいほど全表スキャンのコストは低くなり、結果として、オプティマイザは索引スキャンより全表スキャンを選択することになります。 このパラメータのデフォルト値は、データベースを効果的に実行できる最大I/Oサイズに対応しています。この値は、プラットフォームに依存し、ほとんどのプラットフォームで1MBになります。このパラメータはブロック単位で表されるため、効率的に実行できる最大I/Oサイズを標準ブロック・サイズで除算した値に設定されます。セッション数が非常に大きい場合は、表スキャン・バッファが多すぎてバッファ・キャッシュがあふれないように、マルチブロック読取りカウントの値が減らされます。 |
|
適応計画を制御します。適応計画には代替の選択肢があります。オプティマイザは、問合せの実行時に収集された統計に基づいて、実行時に計画を決定します。 デフォルトでは、このパラメータは
適応問合せ計画についてを参照してください。 |
|
自動再最適化と適応計画のレポート作成モードを制御します(適応問合せ計画を参照)。デフォルトでは、レポート作成モードはオフ(
|
|
適応統計を制御します。最適化は、問合せ述語があまりにも複雑で実表のみを使用できない場合に適応統計を使用できます。 デフォルトでは、
「適応統計」を参照してください。 |
|
データベース・インスタンスの起動時にオプティマイザ・モードを設定します。 |
|
ネステッド・ループとともに索引プローブのコスト分析を制御します。値 |
|
索引プローブのコストを調整します。値の範囲は、 |
|
このパラメータでは、IM列ストア、表拡張、ブルーム・フィルタなどのコスト・モデルを含むすべてのOracle Database In-Memory (Database In-Memory)オプティマイザ機能を有効( |
|
|
OPTIMIZER_SESSION_TYPE |
データベースで自動索引検証中に文を検証するかどうかを指定します。デフォルトは セッションで |
|
非表示の索引の使用を有効化または無効化します。 |
|
オプティマイザのクエリー・リライト機能を有効または無効にします。
|
|
クエリー・リライトを適用する程度を決定します。 デフォルトでは、整合性レベルは 制約が |
|
データベースで使用するSQL問合せ結果キャッシュの対象を、すべての問合せにするのか、または結果キャッシュ・ヒントで注釈付けされた問合せのみにするのかを制御します。 このパラメータを設定する場合は、結果キャッシュでPL/SQLファンクションを処理する方法について検討します。データベースでは、PL/SQLファンクションのデータ依存性を追跡するのと同じメカニズムを使用して結果キャッシュ内の問合せ結果が無効化されますが、それ以外の場合は、PL/SQLファンクションを含む問合せをキャッシュできます。PL/SQLファンクション結果キャッシュの無効化では全種類の依存性(順序、 |
|
結果キャッシュに割り当てられているメモリーを変更します。このパラメータを |
|
すべての単一の結果で使用可能なキャッシュ・メモリーの最大値を指定します。デフォルト値は5%ですが、 |
|
リモート・データベース・オブジェクトに依存する結果の有効時間(分単位)を指定します。デフォルトは |
|
オプティマイザはスター・クエリーのスター型変換のコストを計算できます( |
関連項目:
-
前述の初期化パラメータの詳細は、『Oracle Databaseリファレンス』を参照してください
-
問合せ結果キャッシュのチューニング方法を学習するには、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください
- スター型変換およびクエリー・リライトの詳細についてさらに学習します
-
Database In-Memory機能についてさらに学習するには、Oracle Database In-Memoryガイドを参照してください
19.2.2 オプティマイザ機能の有効化
OPTIMIZER_FEATURES_ENABLE
初期化パラメータ(またはヒント)は一連のオプティマイザ関連機能をデータベース・リリースに応じて制御します。
パラメータによって、11.2.0.2
または12.2.0.1
など、リリース番号に対応する有効な文字列値のいずれかを受け入れます。このパラメータを使用して、データベースのアップグレード後もオプティマイザの以前の動作を保持できます。たとえば、Oracle Database 12cリリース1 (12.1.0.2)からOracle Database 12cリリース2 (12.2.0.1)にアップグレードすると、OPTIMIZER_FEATURES_ENABLE
パラメータのデフォルト値は12.1.0.2
から12.2.0.1
に変更されます。
下位互換性のため、新規リリースの新しいオプティマイザ機能という理由で実行計画の変更を必要とはしない場合もあります。そのような場合は、OPTIMIZER_FEATURES_ENABLE
を以前のバージョンに設定できます。新しいリリースにアップグレードする場合や、新しいリリースの機能を有効化する必要がある場合は、OPTIMIZER_FEATURES_ENABLE
初期化パラメータを明示的に設定する必要はありません。
注意:
OPTIMIZER_FEATURES_ENABLE
初期化パラメータを以前のリリースに明示的に設定することはお薦めしません。実行計画の変更から生じる可能性があるSQLパフォーマンスの低下を回避するには、かわりに、SQL計画管理の使用を検討してください。
前提条件
このチュートリアルでは、次のことが前提となっています。
-
最近、データベースをOracle Database 12cリリース1 (12 1.0.2)からOracle Database 12cリリース2 (12.2.0.1)にアップグレードしました。
-
以前のリリースのオプティマイザ動作を保持したいと思っています。
特定のリリースの問合せオプティマイザ機能を有効化するには:
-
適切な権限でデータベースにログインし、現在のオプティマイザ機能の設定を問い合せます。
たとえば、次のSQL*Plusコマンドを実行します。
SQL> SHOW PARAMETER optimizer_features_enable NAME TYPE VALUE ------------------------------------ ----------- -------- optimizer_features_enable string 12.2.0.1
-
インスタンスまたはセッション・レベルでオプティマイザ機能設定を設定します。
たとえば、次のSQL文を実行してオプティマイザ・バージョンを
12.1.0.2
に設定します。SQL> ALTER SYSTEM SET OPTIMIZER_FEATURES_ENABLE='12.1.0.2';
前述の文では、Oracle Database 12cリリース1 (12.1.0.2)に存在するオプティマイザ機能がリストアされます。
関連項目:
-
OPTIMIZER_FEATURES_ENABLE
を異なるリリースの値に設定する際に有効化されるオプティマイザ機能について学習するには、Oracle Databaseリファレンスを参照してください
19.2.3 オプティマイザの目標の選択
オプティマイザの目標は、オプティマイザによるリソース使用を優先順位付けしたものです。
OPTIMIZER_MODE
初期化パラメータを使用して、次のオプティマイザの目標を設定できます。
-
最高のスループット(デフォルト)
OPTIMIZER_MODE
値をALL_ROWS
に設定すると、データベースでは、文がアクセスしたすべての行の処理に必要な最小限のリソース量が使用されます。Oracle Reportsなどのバッチ・アプリケーションでは、最高のスループットを目標に最適化します。通常、バッチ・アプリケーションでスループットがより重要になるのは、ユーザーが、アプリケーションの完了に必要な時間にのみ関心を持っているためです。アプリケーションの実行中に、ユーザーは個々の文の結果を検証しないため、レスポンス時間はそれほど重要ではありません。
-
最短のレスポンス時間
OPTIMIZER_MODE
値をFIRST_ROWS_
n
に設定すると、データベースでは、最初のn行を戻す最短のレスポンス時間を目標に最適化されます。ここでのnは1
、10
、100
または1000
です。Oracle FormsまたはSQL*Plusの対話型アプリケーションでは、レスポンス時間に対して最適化します。通常、レスポンス時間が重要なのは、文がアクセスした最初の行または数行を確認するために対話型ユーザーが待機しているためです。
前提条件
このチュートリアルでは、次のことが前提となっています。
-
プライマリ・アプリケーションが対話型であるため、データベース・インスタンスにオプティマイザの目標を設定してレスポンス時間を最小化します。
-
現行のセッションの場合のみ、レポート作成を実行し、スループットに対して最適化します。
特定のリリースの問合せオプティマイザ機能を有効化するには:
-
適切な権限でSQL*Plusをデータベースに接続し、現行のオプティマイザ・モードを問い合せます。
たとえば、次のSQL*Plusコマンドを実行します。
dba1@PROD> SHOW PARAMETER OPTIMIZER_MODE NAME TYPE VALUE ------------------------------------ ----------- -------- optimizer_mode string ALL_ROWS
-
インスタンス・レベルで、レスポンス時間に対して最適化します。
たとえば、次のSQL文を実行して、最初の10行をできるかぎり迅速に取得するようにシステムを構成します。
SQL> ALTER SYSTEM SET OPTIMIZER_MODE='FIRST_ROWS_10';
-
セッション・レベルでのみ、レポート作成を実行する前にスループットに対して最適化します。
たとえば、次のSQL文を実行して、スループットに対して最適化するようにこのセッションのみを構成します。
SQL> ALTER SESSION SET OPTIMIZER_MODE='ALL_ROWS';
関連項目:
OPTIMIZER_MODE
初期化パラメータについて学習するには、『Oracle Databaseリファレンス』を参照してください
19.2.4 適応最適化の制御
Oracle Databaseでは、適応問合せ最適化が、実行時に収集された統計に基づいてオプティマイザで実行計画を採用するためのプロセスです。
適応計画は、次の初期化パラメータが設定されたときに有効になります。
-
OPTIMIZER_ADAPTIVE_PLANS
はTRUE
(デフォルト) -
OPTIMIZER_FEATURES_ENABLE
が12.1.0.1
以降 -
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
はFALSE
(デフォルト)
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
がtrue
に設定されている場合は、レポート作成のみのモードで適応最適化が実行されます。この場合は、データベースで適応最適化に必要な情報が収集されるものの、計画は変更されません。適応計画では常にデフォルトの計画が選択されますが、パラメータがfalse
に設定されているかのように実行に関する情報がデータベースで収集されます。
適応統計は、次の初期化パラメータが設定されたときに有効になります。
-
OPTIMIZER_ADAPTIVE_STATISTICS
はTRUE
(デフォルトはFALSE
) -
OPTIMIZER_FEATURES_ENABLE
が12.1.0.1
以降
前提条件
このチュートリアルでは、次のことが前提となっています。
-
OPTIMIZER_FEATURES_ENABLE
初期化パラメータが12.1.0.1
以降に設定されている。 -
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
初期化パラメータがfalse
(デフォルト)に設定されている。 -
テスト目的で適応計画を無効化し、データベースでレポートのみが生成されるようにします。
適応計画を無効化するには:
-
SYSTEM
としてSQL*Plusをデータベースに接続し、現行の設定を問い合せます。たとえば、次のSQL*Plusコマンドを実行します。
SHOW PARAMETER OPTIMIZER_ADAPTIVE_REPORTING_ONLY NAME TYPE VALUE ------------------------------------ ----------- ----- optimizer_adaptive_reporting_only boolean FALSE
-
セッション・レベルで、
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
初期化パラメータをtrue
に設定します。たとえば、SQL*Plusで次のSQL文を実行します。
ALTER SESSION SET OPTIMIZER_ADAPTIVE_REPORTING_ONLY=true;
-
問合せを実行します。
-
DBMS_XPLAN.DISPLAY_CURSOR
を+REPORT
パラメータで実行します。+REPORT
パラメータが設定されると、自動最適化が有効になっている場合、オプティマイザが選択する計画がレポートに表示されます。
関連項目:
-
OPTIMIZER_ADAPTIVE_REPORTING_ONLY
初期化パラメータについて学習するには、『Oracle Databaseリファレンス』を参照してください -
DBMS_XPLAN.DISPLAY_CURSOR
のファンクションの+REPORT
パラメータについて学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
19.3 ヒントによるオプティマイザへの影響
オプティマイザ・ヒントは、命令をオプティマイザに渡すSQL文の特別なコメントです。
オプティマイザは、なんらかの状況に妨害されないかぎり、ヒントを使用して文の実行計画を選択します。
ノート:
すべてのSQLヒントの完全な詳細は、『Oracle Database SQL言語リファレンス』を参照してください
19.3.1 オプティマイザ・ヒントについて
ヒントはSQLコメント内に埋め込まれます。
ヒント・コメントは、SQL文ブロックの最初のキーワードのすぐ後ろに続ける必要があります。スラッシュスター(/*
)またはダッシュのペア(--
)のいずれかのコメント・スタイルを使用できます。プラス記号(+
)のヒント・デリミタは、次のフラグメントのように、プラス記号の前にスペースを入れずに、コメント・デリミタの直後に続ける必要があります。
SELECT /*+ hint_text */ ...
プラス記号の後ろのスペースは任意です。文ブロックでは、ヒントを含むコメントは1つしか持つことができませんが、空白区切りのヒントは多数含むことができます。次の文に示すように、複数のヒントは1つ以上のスペースで区切ります。
SELECT /*+ FULL (hr_emp) CACHE(hr_emp) */ last_name FROM employees hr_emp;
19.3.1.1 ヒントの目的
ヒントを使用すると、通常はオプティマイザによって行われる決定をユーザーが決定できます。
ヒントの使用によって、オプティマイザ・モード、問合せの転送、アクセス・パス、結合順序および結合方法に影響を与えることができます。テスト環境では、特定のアクセス・パスのパフォーマンスをテストする場合にヒントが役に立ちます。たとえば、特定の問合せには索引を選択する方が適切な計画が得られるとわかっていることがあります。次の図は、ヒントを使用してオプティマイザに特定の索引を使用するよう指示する方法を示しています。
ヒントの短所は、管理、チェックおよび制御のためにコードが増えることです。ヒントが導入されたのはOracle7からですが、当時は、オプティマイザによって生成された計画が最善ではない場合にユーザーが取れる手段はほとんどありませんでした。データベースやホスト環境内の変更によってヒントが非推奨となるか、負の結果をもたらす可能性があるため、ヒントを使用したテストが望ましいものの、他の手法を使用して実行計画を管理することがあります。
オプティマイザでは解決されないパフォーマンスの問題に対処するために、SQLチューニング・アドバイザ、SQL計画管理、SQLパフォーマンス・アナライザなどの複数のツールが用意されています。これらのツールにはデータやデータベース環境の変更に対応した新しいソリューションが用意されているため、ヒントのかわりにこれらを使用することを強くお薦めします。
19.3.1.2 ヒントの型
ヒントは、表、問合せブロックおよび文に使用できます。
ヒントは次の型に分類されます。
-
単一表
単一表ヒントは、1つの表またはビュー上で指定します。単一表ヒントの例として、
INDEX
およびUSE_NL
があります。次の文では単一表ヒントが使用されています。SELECT /*+ INDEX (employees emp_department_ix)*/ employee_id, department_id FROM employees WHERE department_id > 50;
-
マルチ表
マルチ表ヒントは単一表ヒントと同様のものですが、ヒントで複数の表またはビューを指定できる点が異なります。マルチ表ヒントの例として、
LEADING
が挙げられます。次の文ではマルチ表ヒントを使用しています。SELECT /*+ LEADING(e j) */ * FROM employees e, departments d, job_history j WHERE e.department_id = d.department_id AND e.hire_date = j.start_date;
ノート:
USE_NL(table1 table2)
は、マルチ表ヒントとはみなされません。これは、USE_NL(table1)
とUSE_NL(table2)
のショートカットであるためです。 -
問合せブロック
問合せブロック・ヒントでは、単一の問合せブロックが処理されます。問合せブロック・ヒントの例として、
STAR_TRANSFORMATION
およびUNNEST
があります。次の文では、問合せブロック・ヒントを使用して、FULL
ヒントがemployees
を参照する問合せブロックにのみ適用されることを指定しています。SELECT /*+ INDEX(t1) FULL(@sel$2 t1) */ COUNT(*) FROM jobs t1 WHERE t1.job_id IN (SELECT job_id FROM employees t1);
-
文
文ヒントはSQL文全体に適用されます。文ヒントの例には、
ALL_ROWS
があります。次の文では文ヒントが使用されています。SELECT /*+ ALL_ROWS */ * FROM sales;
関連項目:
機能カテゴリ別の最も一般的なヒントは、『Oracle Database SQL言語リファレンス』を参照してください。
19.3.1.3 ヒントの有効範囲
文ブロックでヒントを指定すると、そのヒントは文ブロック内の適切な問合せブロック、表または文全体に適用されます。ヒントは、インスタンス・レベルまたはセッション・レベルのどのパラメータよりも優先されます。
文ブロックは次のいずれかです。
-
単純な
MERGE
、SELECT
、INSERT
、UPDATE
またはDELETE
文 -
複合文の親文または副問合せ
-
集合演算子(
UNION
、MINUS
、INTERSECT
)を使用した問合せの一部
例19-1 集合演算子を使用した問合せ
次の問合せは、2つのコンポーネント問合せとUNION
演算子で構成されます。
SELECT /*+ FIRST_ROWS(10) */ prod_id, time_id FROM 2010_sales
UNION ALL
SELECT /*+ ALL_ROWS */ prod_id, time_id FROM current_year_sales;
前述の文には2つのブロックがあり、それぞれが各コンポーネント問合せに対応しています。最初のコンポーネント問合せのヒントはその最適化のみに適用され、2番目のコンポーネント問合せの最適化には適用されません。たとえば、2015年の第1週に現行年度と昨年度の売上を問い合せるとします。昨年度(2014)の売上の問合せにはFIRST_ROWS(10)
を適用し、今年度(2015)の売上の問合せにはALL_ROWS
ヒントを適用します。
関連項目:
ヒントの概要は、『Oracle Database SQL言語リファレンス』を参照してください
19.3.2 結合順序のヒントのガイドライン
場合によっては、結果に影響を及ぼさない行にはアクセスしないように、SQL文で結合順序のヒントを指定することができます。
結合における駆動表は、その他の表が結合された表です。通常、駆動表には、表内を最も高い割合で排除するフィルタ条件が含まれています。結合順序は、SQL文のパフォーマンスに大きな影響を与えることがあります。
次のガイドラインを念頭に置いてください。
-
索引によって、要求された行がより効率的に取得される場合は、全表スキャンを実行しないでください。
-
少数の行をフェッチする索引を使用できる場合には、駆動表から多数の行をフェッチする索引を使用するようなことは避けてください。
-
結合順序の後ろへ行くほど結合する行が少なくなるように結合順序を選択してください。
次の例は、結合順序を効果的にチューニングする方法を示しています。
SELECT *
FROM taba a,
tabb b,
tabc c
WHERE a.acol BETWEEN 100 AND 200
AND b.bcol BETWEEN 10000 AND 20000
AND c.ccol BETWEEN 10000 AND 20000
AND a.key1 = b.key1
AND a.key2 = c.key2;
-
駆動表と駆動索引(存在する場合)を選択します。
前述の例における最初の3つの条件はそれぞれ、1つの表に適用されるフィルタ条件です。最後の2つの条件は結合条件です。
フィルタ条件は、駆動表と駆動索引の選択を左右します。通常、駆動表には、行を最も高い割合で排除するフィルタ条件が含まれています。100から200の範囲は
acol
の範囲に比べて狭く、10000から20000の範囲は相対的に大きいため、taba
は駆動表になり、その他はすべて同じになります。ネステッド・ループ結合の場合、結合索引を介して結合します。この結合索引は、主キーまたは外部キーに付けられているもので、その表を結合ツリー内のそれより前にある表に結び付けるために使用します。駆動表を除いて、非結合条件にこの結合索引を使用することはほとんどありません。そのため、
taba
を駆動表として選択した後、b.key1
とc.key2
の索引を使用してtabb
とtabc
をそれぞれ駆動します。 -
未使用の最適なフィルタを最初に駆動する最適な結合順序を選択します。
最適な未使用フィルタを持つ表に先に結合することで、その後の結合の作業を削減できます。したがって、
bcol BETWEEN
がccol BETWEEN
よりも限定的な(行をより高い比率で排除する)場合は、tabb
をtabc
よりも前に結合すると、最後の結合が容易になります(行数が少なくなります)。 -
ORDERED
またはSTAR
ヒントを使用して、結合順序を強制的に設定できます。
関連項目:
OPTIMIZER_MODE
について学習するには、『Oracle Databaseリファレンス』を参照してください
19.3.3 ヒントに関するレポート
説明された計画には、計画の生成時に使用されたヒントを示すレポートが含まれています。
19.3.3.1 ヒント使用状況レポートの目的
Oracle Database 19cより前のリリースでは、オプティマイザがヒントを使用しなかった理由を知ることが困難な場合がありました。ヒント使用状況レポートにより、この問題が解決されます。
オプティマイザは、ヒント内のエンコードされた命令を使用して文の実行計画を選択します。ただし、条件によってはオプティマイザがヒントを使用しないことがあります。データベースでは、無視したヒントに対してエラー・メッセージは発行されません。ヒント・レポートには、使用されたヒントと無視されたヒントが表示されます。通常はヒントが無視された理由も示されます。ヒントが無視される最も一般的な理由は、次のとおりです。
-
構文エラー
ヒントには、入力ミスや無効な引数が含まれていることがあります。同じヒント・ブロックに複数のヒントがあり、そのうちの1つのヒントに構文エラーがあると、オプティマイザはエラーがあるヒントの前までのすべてのヒントを考慮に入れますが、その後にあるヒントを無視します。たとえば、ヒント指定
/*+ INDEX(t1) FULL(t2) MERG(v) USE_NL(t2) */
のMERG(v)
には構文エラーがあります。オプティマイザはINDEX(t1)
とFULL(t2)
を考慮に入れますが、MERG(v)
とUSE_NL(t2)
を無視します。ヒント使用状況レポートには、エラーがあるものとしてMERG(v)
が示されます。ただし、USE_NL(t2)
は解析されないためレポートに示されません。 -
未解決のヒント
未解決のヒントは、構文エラー以外の理由により無効です。たとえば、文で
INDEX(employees emp_idx)
を指定していて、emp_idx
が表employees
の有効な索引名ではない場合です。 -
競合するヒント
競合するヒントの組合せは、それらのヒントが正しく指定されていたとしてもデータベースによって無視されます。たとえば、文で
FULL(employees) INDEX(employees)
を指定していても、索引スキャンと全表スキャンは同時に両方実行することはできません。ほとんどの場合、オプティマイザは競合するヒントを両方とも無視します。 -
変換の影響を受けるヒント
一部のヒントは、変換によって無効になる場合があります。たとえば、文で
PUSH_PRED(some_view) MERGE(some_view)
を指定している場合です。some_view
が、それを含む問合せブロックにマージされると、some_view
が使用できなくなるため、オプティマイザはPUSH_PRED
ヒントを適用できなくなります。
関連項目:
コメントおよびヒントの構文ルールについて学習するには、Oracle Database SQL言語リファレンスを参照してください
19.3.3.2 ヒント使用状況レポートのユーザー・インタフェース
このレポートには、すべてのオプティマイザ・ヒントのステータスが表示されます。その他のヒントのサブセット(PARALLEL
やINMEMORY
など)も示されます。
レポート・アクセス
ヒントのトラッキングはデフォルトで有効になっています。ヒント使用状況レポートにアクセスするには、次のDBMS_XPLAN
関数を使用します。
-
DISPLAY
-
DISPLAY_CURSOR
-
DISPLAY_WORKLOAD_REPOSITORY
-
DISPLAY_SQL_PLAN_BASELINE
-
DISPLAY_SQLSET
前述の関数は、format
パラメータで値HINT_REPORT
を指定すると、レポートを生成します。値TYPICAL
を指定すると最終プランでは使用されていないヒントのみが表示されますが、値ALL
を指定すると使用されたヒントと使用されていないヒントの両方が表示されます。
レポート・フォーマット
次のヒント付き問合せを説明するとします。
SELECT /*+ INDEX(t1) FULL(@sel$2 t1) */ COUNT(*)
FROM jobs t1
WHERE t1.job_id IN (SELECT /*+ FULL(t1) */ job_id FROM employees t1);
次のDBMS_XPLAN.DISPLAY
の出力では、ヒント・レポートを含む計画を示しています。
---------------------------------------------------------------------------
| Id| Operation | Name | Rows | Bytes | Cost (%CPU)| Time|
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 3 (34)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 17 | | |
| 2 | NESTED LOOPS | | 19 | 323 | 3 (34)| 00:00:01 |
| 3 | SORT UNIQUE | | 107 | 963 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| EMPLOYEES | 107 | 963 | 2 (0)| 00:00:01 |
|*5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | 8 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
4 - SEL$5DA710D3 / "T1"@"SEL$2"
5 - SEL$5DA710D3 / "T1"@"SEL$1"
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("T1"."JOB_ID"="JOB_ID")
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - (#keys=0) COUNT(*)[22]
2 - (#keys=0)
3 - (#keys=1) "JOB_ID"[VARCHAR2,10]
4 - (rowset=256) "JOB_ID"[VARCHAR2,10]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 3 (U - Unused (1))
---------------------------------------------------------------------------
4 - SEL$5DA710D3 / "T1"@"SEL$2"
U - FULL(t1) / hint overridden by another in parent query block
- FULL(@sel$2 t1)
5 - SEL$5DA710D3 / "T1"@"SEL$1"
- INDEX(t1)
レポートのヘッダーには、レポート内のヒントの合計数が示されます。この場合、文には合計3つのヒントが含まれています。ヒントが未使用、未解決の場合やヒントに構文エラーがある場合、ヘッダーにはその数が示されます。この場合、1つのヒントのみが未使用になっています。
レポートでは、計画に出現するオブジェクト(問合せブロックや表など)の下にヒントが表示されます。各オブジェクトの前にある番号によって、計画内でオブジェクトが最初に出現する行を識別できます。たとえば、前述のレポートには、個別のオブジェクトT1@SEL$2
およびT1@SEL$1
に適用されるヒントが示されています。表T1@SEL$2
は、計画の行4で問合せブロックSEL$5DA710D3
内に現れます。表T1@SEL$1
は、計画の行5で同じ問合せブロックに現れます。
ヒントは、不正確に指定されることや、最終計画に存在しないオブジェクトに関連付けられることもあります。問合せブロックが最終計画に現れない場合、レポートでは、その問合せブロックに行番号0
が割り当てられます。前述の例では、行番号0のヒントがないため、すべての問合せブロックが最終計画に現れます。
このレポートには、ヒントのテキストが表示されます。ヒントには、次のいずれかの注釈が付いているものもあります。
-
E
は、構文エラーを示します。 -
N
は、未解決のヒントを示します。 -
U
は、最終計画で対応するヒントが使用されなかったことを示します。
前述の例では、U - FULL(t1)
は、問合せブロックSEL$5DA710D3
が最終計画に現れたが、FULL(t1)
ヒントは適用されなかったことを示しています。
それぞれのオブジェクトでは、未使用のヒントが最初に表示され、その後に使用されたヒントが表示されます。たとえば、レポートには、使用されなかったFULL(t1)
ヒントが最初に表示され、その後に使用されたFULL(@sel$2t1)
が表示されます。多くの未使用のヒントについて、レポートには、オプティマイザがヒントを適用しなかった理由が示されます。前述の例では、FULL(t1)
はhint overridden by another in parent query block
という理由で使用されなかったことがレポートに示されています。
関連項目:
DBMS_XPLAN
パッケージについてさらに学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照
19.3.3.3 ヒント使用状況に関するレポート: チュートリアル
ヒント使用状況に関するレポートには、DBMS_XPLAN
表示関数を使用できます。
前提条件
このチュートリアルでは、次のことが前提となっています。
-
employees.employee_id
列に対する索引emp_emp_id_pk
が存在している。 -
特定の従業員を問い合せようとしている。
-
オプティマイザに
emp_emp_id_pk
の使用を強制するために、INDEX
ヒントを使用しようとしている。
ヒント使用状況に関するレポートの作成には:
-
SQL*PlusまたはSQL Developerを起動して、ユーザー
hr
としてデータベースにログインします。 -
employees
の問合せに対する計画をEXPLAINします。たとえば、次の文を入力します。
EXPLAIN PLAN FOR SELECT /*+ INDEX(e emp_emp_id_pk) */ COUNT(*) FROM employees e WHERE e.employee_id = 5;
-
表示関数を使用して、PLAN TABLEを問い合せます。
format
パラメータには、次のいずれかの値を指定できます。-
ALL
-
TYPICAL
次の問合せでは、ヒント使用状況の情報を含む計画のすべてのセクションが表示されます(出力例も示します)。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'ALL')); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------- Plan hash value: 2637910222 ---------------------------------------------------------------------- |Id | Operation | Name |Rows|Bytes | Cost (%CPU)| Time| ---------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 0 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | |*2 | INDEX UNIQUE SCAN| EMP_EMP_ID_PK | 1 | 4 | 0 (0)| 00:00:01 | ---------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ---------------------------------------------------------------------- 1 - SEL$1 2 - SEL$1 / E@SEL$1 Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("E"."EMPLOYEE_ID"=5) Column Projection Information (identified by operation id): ---------------------------------------------------------------------- 1 - (#keys=0) COUNT(*)[22] Hint Report (identified by operation id/Query Block Name/Object Alias) Total hints for statement: 1 ---------------------------------------------------------------------- 2 - SEL$1 / E@SEL$1 - INDEX(e emp_emp_id_pk)
「Hint Report」セクションには、
INDEX(e emp_emp_id_pk)
ヒントの問合せブロックがSEL$1
になっていることが示されています。表の識別子は、E@SEL$1
です。計画行の行番号は2
です。これは、表E@SEL$1
がPLAN TABLEに現れる最初の行と一致します。 -
関連項目:
EXPLAIN PLAN
についてさらに学習するには、『Oracle Database SQL言語リファレンス』を参照
19.3.3.4 ヒント使用状況レポート: 例
ここでは、様々なタイプのヒント使用状況レポートの例を示します。
次の例では、hr
スキーマでの表の問合せをすべて表示します。
例19-2 文レベルの未使用ヒント
次の例では、emp_manager_ix
索引に索引範囲ヒントを指定します。
EXPLAIN PLAN FOR
SELECT /*+ INDEX_RS(e emp_manager_ix) */ COUNT(*)
FROM employees e
WHERE e.job_id < 5;
次のPLAN TABLEの問合せでは、format
値に未使用のヒントのみを示すTYPICAL
を指定しています。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'TYPICAL'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 2731009358
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes| Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 9 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 9 | | |
|* 2 | INDEX FULL SCAN| EMP_JOB_IX | 5 | 45 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
2 - filter(TO_NUMBER("E"."JOB_ID")<5)
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1 (U - Unused (1))
---------------------------------------------------------------------------
2 - SEL$1 / E@SEL$1
U - INDEX_RS(e emp_manager_ix)
前述のヒント使用状況レポートにあるU
は、INDEX_RS
ヒントが使用されなかったことを示しています。このレポートには、未使用のヒントの合計数が表示されます(U – Unused (1)
)。
例19-3 競合するヒント
次の例では、2つのヒント(スキップ・スキャンと高速全スキャンのヒント)を指定します。
EXPLAIN PLAN FOR
SELECT /*+ INDEX_SS(e emp_manager_ix) INDEX_FFS(e) */ COUNT(*)
FROM employees e
WHERE e.manager_id < 5;
次のPLAN TABLEの問合せでは、format
値に未使用のヒントのみを示すTYPICAL
を指定しています。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'TYPICAL'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 2262146496
---------------------------------------------------------------------------
| Id| Operation | Name |Rows |Bytes |Cost (%CPU)|Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
|*2 | INDEX RANGE SCAN| EMP_MANAGER_IX | 1 | 4 | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
2 - access("E"."MANAGER_ID"<5)
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 2 (U - Unused (2))
---------------------------------------------------------------------------
2 - SEL$1 / E@SEL$1
U - INDEX_FFS(e) / hint conflicts with another in sibling query block
U - INDEX_SS(e emp_manager_ix) / hint conflicts with another in
sibling query block
前述のレポートは、INDEX_FFS(e)
ヒントとINDEX_SS(e emp_manager_ix)
ヒントが相互に競合していることを示しています。索引スキップ・スキャンと高速全索引スキャンは相互に排他的です。オプティマイザは、テキスト「U — Unused (2)
」で示されているように、両方のヒント無視しました。オプティマイザは、emp_manager_ix
索引を指定するヒントを無視しましたが、この索引自体はコストベースの分析に基づいて使用されています。
例19-4 マルチ表ヒント
次の例では、4つのヒントを指定していますが、そのうちの1つは2つの表を指定しています。
EXPLAIN PLAN FOR
SELECT /*+ ORDERED USE_NL(t1, t2) INDEX(t2) NLJ_PREFETCH(t2) */ COUNT(*)
FROM jobs t1, employees t2
WHERE t1.job_id = t2.employee_id;
次のPLAN TABLEの問合せでは、format
値にALL
を指定しています。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'ALL'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 2668549896
---------------------------------------------------------------------------
| Id | Operation | Name |Rows |Bytes |Cost (%CPU)|Time|
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 12 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 12 | | |
| 2 | NESTED LOOPS | | 19 | 228 | 1 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | JOB_ID_PK | 19 | 152 | 1 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN| EMP_EMP_ID_PK | 1 | 4 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
3 - SEL$1 / T1@SEL$1
4 - SEL$1 / T2@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T2"."EMPLOYEE_ID"=TO_NUMBER("T1"."JOB_ID"))
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - (#keys=0) COUNT(*)[22]
2 - (#keys=0)
3 - "T1"."JOB_ID"[VARCHAR2,10]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 5 (U - Unused (2))
---------------------------------------------------------------------------
1 - SEL$1
- ORDERED
3 - SEL$1 / T1@SEL$1
U - USE_NL(t1, t2)
4 - SEL$1 / T2@SEL$1
U - NLJ_PREFETCH(t2)
- INDEX(t2)
- USE_NL(t1, t2)
前述のレポートは、2つのヒントUSE_NL(t1, t2)
とNLJ_PREFETCH(t2)
が使用されなかったことを示しています。計画のステップ3は、jobs
表(別名t1
)の全索引スキャンです。このレポートは、オプティマイザがjobs
のアクセスにUSE_NL(t1, t2)
ヒントを適用しなかったことを示しています。ステップ4は、employees
表(別名t2
)の索引一意スキャンです。USE_NL(t1, t2)
にはU
の接頭辞が付いていないことから、オプティマイザがemployees
のヒントを使用したことがわかります。
例19-5 未使用の問合せブロックのヒント
次の例では、副問合せに2つのヒントUNNEST
とSEMIJOIN
を指定します。
EXPLAIN PLAN FOR
SELECT COUNT(*), manager_id
FROM departments
WHERE manager_id IN (SELECT /*+ UNNEST SEMIJOIN */ manager_id FROM employees)
AND ROWNUM <= 2
GROUP BY manager_id;
次のPLAN TABLEの問合せでは、format
値にALL
を指定しています。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'ALL'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 173733304
---------------------------------------------------------------------------
| Id |Operation | Name |Rows |Bytes |Cost (%CPU)|Time|
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 14 | 3 (34)| 00:00:01 |
| 1 | HASH GROUP BY | | 2 | 14 | 3 (34)| 00:00:01 |
|*2 | COUNT STOPKEY | | | | | |
| 3 | NESTED LOOPS SEMI | | 2 | 14 | 2 (0)| 00:00:01 |
|*4 | TABLE ACCESS FULL| DEPARTMENTS | 2 | 6 | 2 (0)| 00:00:01 |
|*5 | INDEX RANGE SCAN | EMP_MANAGER_IX | 107|428 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
4 - SEL$5DA710D3 / DEPARTMENTS@SEL$1
5 - SEL$5DA710D3 / EMPLOYEES@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(ROWNUM<=2)
4 - filter("MANAGER_ID" IS NOT NULL)
5 - access("MANAGER_ID"="MANAGER_ID")
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - (#keys=1) "MANAGER_ID"[NUMBER,22], COUNT(*)[22]
2 - "MANAGER_ID"[NUMBER,22]
3 - (#keys=0) "MANAGER_ID"[NUMBER,22]
4 - "MANAGER_ID"[NUMBER,22]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 2
---------------------------------------------------------------------------
0 - SEL$2
- SEMIJOIN
- UNNEST
この例では、問合せブロックSEL$2
にヒントが指定されていますが、最終計画にSEL$2
は現れません。このレポートでは、対応する行番号が0
のSEL$2
の下にヒントが表示されています。
例19-6 オーバーライドされたヒント
次の例では、同じ問合せブロックの同じ表に2つのFULL
ヒントを指定します。
EXPLAIN PLAN FOR
SELECT /*+ INDEX(t1) FULL(@sel$2 t1) */ COUNT(*)
FROM jobs t1
WHERE t1.job_id IN (SELECT /*+ FULL(t1) NO_MERGE */ job_id FROM employees t1);
次のPLAN TABLEの問合せでは、format
値にALL
を指定しています。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(format => 'ALL'));
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 3101158531
---------------------------------------------------------------------------
| Id | Operation | Name |Rows |Bytes |Cost (%CPU)|Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 3 (34)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 17 | | |
| 2 | NESTED LOOPS | | 19 | 323 | 3 (34)| 00:00:01 |
| 3 | SORT UNIQUE | |107 | 963 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| EMPLOYEES |107 | 963 | 2 (0)| 00:00:01 |
|* 5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | 8 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$5DA710D3
4 - SEL$5DA710D3 / T1@SEL$2
5 - SEL$5DA710D3 / T1@SEL$1
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("T1"."JOB_ID"="JOB_ID")
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - (#keys=0) COUNT(*)[22]
2 - (#keys=0)
3 - (#keys=1) "JOB_ID"[VARCHAR2,10]
4 - (rowset=256) "JOB_ID"[VARCHAR2,10]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 4 (U - Unused (1))
---------------------------------------------------------------------------
0 - SEL$2
- NO_MERGE
4 - SEL$5DA710D3 / T1@SEL$2
U - FULL(t1) / hint overridden by another in parent query block
- FULL(@sel$2 t1)
5 - SEL$5DA710D3 / T1@SEL$1
- INDEX(t1)
指定された3つのヒントのうち、1つのみが未使用でした。問合せブロックSEL$2
で指定したヒントFULL(t1)
は、問合せブロックSEL$1
で指定したヒントFULL(@sel$2 T1)
によってオーバーライドされました。問合せブロックSEL$2
のNO_MERGE
ヒントが使用されました。
次のPLAN TABLEの問合せでは、formatの設定に未使用のヒントのみ示すTYPICAL
を使用しています。
SQL> select * from table(dbms_xplan.display(format => 'TYPICAL'));
Plan hash value: 3101158531
---------------------------------------------------------------------------
| Id | Operation | Name |Rows |Bytes |Cost (%CPU)|Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 17 | 3 (34)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 17 | | |
| 2 | NESTED LOOPS | | 19 | 323 | 3 (34)| 00:00:01 |
| 3 | SORT UNIQUE | | 107 | 963 | 2 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL| EMPLOYEES | 107 | 963 | 2 (0)| 00:00:01 |
|* 5 | INDEX UNIQUE SCAN | JOB_ID_PK | 1 | 8 | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("T1"."JOB_ID"="JOB_ID")
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 1 (U - Unused (1))
---------------------------------------------------------------------------
4 - SEL$5DA710D3 / T1@SEL$2
U - FULL(t1) / hint overridden by another in parent query block
例19-7 複数のヒント
次のUNION ALL
問合せでは、10個の異なるヒントを指定しています。
SELECT /*+ FULL(t3) INDEX(t2) INDEX(t1) MERGE(@SEL$5) PARALLEL(2) */ t1.first_name
FROM employees t1, jobs t2, job_history t3
WHERE t1.job_id = t2.job_id
AND t2.min_salary = 100000
AND t1.department_id = t3.department_id
UNION ALL
SELECT /*+ INDEX(t3) USE_MERGE(t2) INDEX(t2) FULL(t1) NO_ORDER_SUBQ */ t1.first_name
FROM departments t3, jobs t2, employees t1
WHERE t1.job_id = t2.job_id
AND t2.min_salary = 100000
AND t1.department_id = t3.department_id;
次の共有SQL領域の問合せでは、ALL
のformat
値を指定しています(計画の行は読みやすくするために切り詰められています)。
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(format => 'ALL'))
...
-------------------------------------------------------------------------------------------
| Id | Operation | Name |Rows |Bytes |Cost (%CPU)|
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 9 (100)|
| 1 | UNION-ALL | | | | |
| 2 | PX COORDINATOR | | | | |
| 3 | PX SEND QC (RANDOM) | :TQ10002 | 5 | 175 | 5 (0)|
|* 4 | HASH JOIN | | 5 | 175 | 5 (0)|
| 5 | PX RECEIVE | | 3 | 93 | 3 (0)|
| 6 | PX SEND BROADCAST | :TQ10001 | 3 | 93 | 3 (0)|
| 7 | NESTED LOOPS | | 3 | 93 | 3 (0)|
| 8 | NESTED LOOPS | | 6 | 93 | 3 (0)|
|* 9 | TABLE ACCESS BY INDEX ROWID BATCHED| JOBS | 1 | 12 | 2 (0)|
| 10 | BUFFER SORT | | | | |
| 11 | PX RECEIVE | | 19 | | 1 (0)|
| 12 | PX SEND HASH (BLOCK ADDRESS) | :TQ10000 | 19 | | 1 (0)|
| 13 | PX SELECTOR | | | | |
| 14 | INDEX FULL SCAN | JOB_ID_PK | 19 | | 1 (0)|
|* 15 | INDEX RANGE SCAN | EMP_JOB_IX | 6 | | 0 (0)|
| 16 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES | 6 | 114 | 1 (0)|
| 17 | PX BLOCK ITERATOR | | 10 | 40 | 2 (0)|
|* 18 | TABLE ACCESS FULL | JOB_HISTORY | 10 | 40 | 2 (0)|
| 19 | PX COORDINATOR | | | | |
| 20 | PX SEND QC (RANDOM) | :TQ20002 | 3 | 93 | 4 (0)|
|* 21 | HASH JOIN | | 3 | 93 | 4 (0)|
| 22 | JOIN FILTER CREATE | :BF0000 | 1 | 12 | 2 (0)|
| 23 | PX RECEIVE | | 1 | 12 | 2 (0)|
| 24 | PX SEND BROADCAST | :TQ20001 | 1 | 12 | 2 (0)|
|* 25 | TABLE ACCESS BY INDEX ROWID BATCHED | JOBS | 1 | 12 | 2 (0)|
| 26 | BUFFER SORT | | | | |
| 27 | PX RECEIVE | | 19 | | 1 (0)|
| 28 | PX SEND HASH (BLOCK ADDRESS) | :TQ20000 | 19 | | 1 (0)|
| 29 | PX SELECTOR | | | | |
| 30 | INDEX FULL SCAN | JOB_ID_PK | 19 | | 1 (0)|
| 31 | JOIN FILTER USE | :BF0000 | 106 | 2014 | 2 (0)|
| 32 | PX BLOCK ITERATOR | | 106 | 2014 | 2 (0)|
|* 33 | TABLE ACCESS FULL | EMPLOYEES | 106 | 2014 | 2 (0)|
-------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SET$1
4 - SEL$1
9 - SEL$1 / T2@SEL$1
14 - SEL$1 / T2@SEL$1
15 - SEL$1 / T1@SEL$1
16 - SEL$1 / T1@SEL$1
18 - SEL$1 / T3@SEL$1
21 - SEL$E0F432AE
25 - SEL$E0F432AE / T2@SEL$2
30 - SEL$E0F432AE / T2@SEL$2
33 - SEL$E0F432AE / T1@SEL$2
Predicate Information (identified by operation id):
-----------------------------------------------------------
4 - access("T1"."DEPARTMENT_ID"="T3"."DEPARTMENT_ID")
9 - filter("T2"."MIN_SALARY"=100000)
15 - access("T1"."JOB_ID"="T2"."JOB_ID")
18 - access(:Z>=:Z AND :Z<=:Z)
21 - access("T1"."JOB_ID"="T2"."JOB_ID")
25 - filter("T2"."MIN_SALARY"=100000)
33 - access(:Z>=:Z AND :Z<=:Z)
filter(("T1"."DEPARTMENT_ID" IS NOT NULL AND
SYS_OP_BLOOM_FILTER(:BF0000,"T1"."JOB_ID")))
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - STRDEF[20]
2 - "T1"."FIRST_NAME"[VARCHAR2,20]
3 - (#keys=0) "T1"."FIRST_NAME"[VARCHAR2,20]
4 - (#keys=1; rowset=256) "T1"."FIRST_NAME"[VARCHAR2,20]
5 - (rowset=256) "T1"."DEPARTMENT_ID"[NUMBER,22], "T1"."FIRST_NAME"[VARCHAR2,20]
6 - (#keys=0) "T1"."DEPARTMENT_ID"[NUMBER,22], "T1"."FIRST_NAME"[VARCHAR2,20]
7 - "T1"."FIRST_NAME"[VARCHAR2,20], "T1"."DEPARTMENT_ID"[NUMBER,22]
8 - "T1".ROWID[ROWID,10]
9 - "T2"."JOB_ID"[VARCHAR2,10]
10 - (#keys=0) "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
11 - (rowset=256) "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
12 - (#keys=1) "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
13 - "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
14 - "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
15 - "T1".ROWID[ROWID,10]
16 - "T1"."FIRST_NAME"[VARCHAR2,20], "T1"."DEPARTMENT_ID"[NUMBER,22]
17 - (rowset=256) "T3"."DEPARTMENT_ID"[NUMBER,22]
18 - (rowset=256) "T3"."DEPARTMENT_ID"[NUMBER,22]
19 - "T1"."FIRST_NAME"[VARCHAR2,20]
20 - (#keys=0) "T1"."FIRST_NAME"[VARCHAR2,20]
21 - (#keys=1; rowset=256) "T1"."FIRST_NAME"[VARCHAR2,20]
22 - (rowset=256) "T2"."JOB_ID"[VARCHAR2,10]
23 - (rowset=256) "T2"."JOB_ID"[VARCHAR2,10]
24 - (#keys=0) "T2"."JOB_ID"[VARCHAR2,10]
25 - "T2"."JOB_ID"[VARCHAR2,10]
26 - (#keys=0) "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
27 - (rowset=256) "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
28 - (#keys=1) "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
29 - "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
30 - "T2".ROWID[ROWID,10], "T2"."JOB_ID"[VARCHAR2,10]
31 - (rowset=256) "T1"."FIRST_NAME"[VARCHAR2,20], "T1"."JOB_ID"[VARCHAR2,10]
32 - (rowset=256) "T1"."FIRST_NAME"[VARCHAR2,20], "T1"."JOB_ID"[VARCHAR2,10]
33 - (rowset=256) "T1"."FIRST_NAME"[VARCHAR2,20], "T1"."JOB_ID"[VARCHAR2,10]
Hint Report (identified by operation id / Query Block Name / Object Alias):
Total hints for statement: 10 (U - Unused (2), N - Unresolved (1), E - Syntax error (1))
----------------------------------------------------------------------------------------
0 - STATEMENT
- PARALLEL(2)
0 - SEL$5
N - MERGE(@SEL$5)
0 - SEL$2
E - NO_ORDER_SUBQ
9 - SEL$1 / T2@SEL$1
- INDEX(t2)
15 - SEL$1 / T1@SEL$1
- INDEX(t1)
18 - SEL$1 / T3@SEL$1
- FULL(t3)
21 - SEL$E0F432AE / T3@SEL$2
U - INDEX(t3)
25 - SEL$E0F432AE / T2@SEL$2
U - USE_MERGE(t2)
- INDEX(t2)
33 - SEL$E0F432AE / T1@SEL$2
- FULL(t1)
Note
-----
- Degree of Parallelism is 2 because of hint
このレポートには、次の未使用のヒントが示されています。
-
2つの未使用ヒント(
U
)このレポートは、
INDEX(t3)
とUSE_MERGE(t2)
が、問合せブロックSEL$E0F432AE
で使用されなかったことを示しています。 -
1つの未解決ヒント(
N
)ヒント
MERGE
は、問合せブロックSEL$5
が存在しないため解決されていません。 -
1つの構文エラー(
E
)SEL$2
で指定されたヒントNO_ORDER_SUBQ
は、有効なヒントではありません。