オプティマイザーのデフォルトの結合順序は、統計情報が不十分な場合や選択性(selectivity)を誤って予測した場合に、非最適なクエリプランを生成することがあります。LEADING ヒントワードを使用すると、オプティマイザーが最初に処理するテーブルを明示的に指定することで、この判断をオーバーライドできます。残りのテーブルについては、引き続きオプティマイザーが最適な結合順序を自動的に決定します。
結合シーケンスにおける先頭テーブル(ドライビングテーブル)は、パフォーマンスに大きな影響を与えます。フィルター条件により、できるだけ多くの行を早期に除外できるテーブルを選択してください。後続の結合に渡される行数が少なくなるほど、全体の処理量が削減されます。オプティマイザーが不適切なドライビングテーブルを選択した場合は、LEADING ヒントワードで修正してください。
注意事項
ネストされた SQL ステートメント内では LEADING ヒントワードはサポートされていません。予期しない結果を最小限に抑えるため、句(clause)内での使用は避けてください。
複数テーブルの結合順序をオプティマイザーが生成する際には、結合条件が設定されているテーブルが優先されます。実行計画が生成できない場合にのみ、システムはデカルト積を試行します。
結合条件が設定された 2 つの隣接テーブルに対して LEADING ヒントワードを使用する場合、後続テーブルは直前のテーブルと即座に結合されます。それ以外の場合、実行計画が生成できないため、LEADING ヒントワードは無視されます。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
ヒント機能が有効化された PolarDB for PostgreSQL (Compatible with Oracle) インスタンス(デフォルトで有効)
ヒント機能を手動で有効化するには、次のコマンドを実行します。
set enable_hints = true;構文
ヒントワードは以下の形式に従います。
/*+ hint_name(parameters) */構文ルール:
ヒントワードは
/*+で開始し、*/で終了します。*と+の間に空白文字を入れてはいけません。パラメーターは半角スペースで区切ります。
ヒントワードは、DML キーワード(SELECT、UPDATE、INSERT、MERGE、DELETE)の直後に配置します。
ヒントワードは大文字・小文字を区別しません。
LEADING ヒントワードが無視される場合
以下の場合、オプティマイザーは LEADING ヒントワードを静かに無視します。
| 状況 | 結果 |
|---|---|
| 依存関係により、指定されたテーブルを所定の順序で結合できない場合 | すべての LEADING ヒントワードが無視される |
| 複数の LEADING ヒントワードが指定されている場合 | すべての LEADING ヒントワードが無視される |
| ORDERED ヒントワードと LEADING ヒントワードの両方が指定されている場合 | ORDERED がすべての LEADING ヒントワードを上書きする |
テーブル名またはエイリアスにピリオド(.)が含まれている場合(例:s.t | すべての LEADING ヒントワードが無視される |
| ヒントワードが SELECT、UPDATE、INSERT、MERGE、DELETE の直後に配置されていない場合 | その LEADING ヒントワードが無視される |
| LEADING ヒントワードがネストされた SQL ステートメントまたはサブクエリ内に記述されている場合 | その LEADING ヒントワードが無視される |
例
以下の例では、相互に結合可能な 4 つのテーブル — a、b、c、および d — を使用します。
有効な構文
| ヒント | 可能な結合順序 |
|---|---|
/*+ leading(a) */ | (((a b) c) d)、(((a b) d) c)、(((a c) b) d)、(((a c) d) b)、(((a d) b) c)、(((a c) c) b) |
/*+ leading(a b) */ | (((a b) c) d)、(((a b) d) c) |
/*+ leading(a b c) */ | (((a b) c) d) |
/*+ leading(a b c d) */ | (((a b) c) d) |
((a b) c) は、まず a と b を結合し、その結果を c と結合することを意味します。(c (a b)) は、まず c を結合対象とし、その後に a と b を結合することを意味します。指定するテーブル数が多くなるほど、結合順序の制約は厳しくなります。すべてのテーブルを指定すると、単一の結合順序が固定されます。無効な構文
以下の例はすべて無効です。
/* + leading(a) */—/と*の間に空白文字が含まれている/*+ leading(a b) leading(a b) */— 重複する LEADING ヒントワード/*+ leading(a b a) */— パラメーター一覧内でテーブル名が重複している/*+ leading(a b) leading(a) *//*+ leading(a b) leading(c d) *//*+ leading(a b e) */— データベースにテーブルeが存在しない*+ leading(a b) leading(a c) */— 先頭に/が欠落している/*+ leading() */— パラメーター一覧が空である