ヒントはSQLステートメントのコメントであり、OceanBaseデータベースのオプティマイザーに指示を伝えるために使用されます。ヒントを使用することで、オプティマイザーが指定された実行計画を生成させることができます。
通常、オプティマイザーはユーザーのクエリに対して最適な実行計画を選択します。そのため、ユーザーがヒントを使用して指定する必要はありません。しかし、オプティマイザーが生成した実行計画がユーザーの要件を満たせない可能性がある場合、ユーザーはヒントを使用して特別な実行計画を明示的に指定し、生成する必要があります。
注意点として、関連テーブルの統計情報を収集し、ヒントを使用せずに EXPLAIN PLAN ステートメントでオプティマイザーの計画を評価した後であれば、慎重にヒントの使用を検討することをお勧めします。データベースの条件変更や、今後のバージョンでのクエリパフォーマンスの向上により、コード内のヒントがパフォーマンスに大きな影響を与える可能性があります。
ヒントの使用方法
ヒントの使用方法と注意点
1つのステートメントには1つのヒントコメントしか含めることができず、そのコメントは CREATE、SELECT、UPDATE、INSERT、REPLACE、または DELETE キーワードの後に続けなければなりません。ヒントはオプティマイザーが生成する実行計画のロジックにのみ影響を与え、SQLステートメントの意味には影響しません。
- ステートメントコメント内でのヒントの構文は以下のとおりです:
{CREATE|DELETE|INSERT|SELECT|UPDATE|REPLACE} /*+ hint_text [,hint_text...] */
ヒントを定義する際の注意事項:
ヒントは構文的には特殊なSQLコメントであり、コメントは
/*+で始まり、スペースは使用できません。サーバー側がSQLステートメント内のヒントを認識できない場合、オプティマイザーはユーザーが指定したヒントを無視し、デフォルトの計画で生成された実行ロジックを使用することを選択します。
各
SELECTなどのキーワードの後には、1つのヒントセグメントのみを追加できます。このヒントセグメント内部には複数のヒントを含めることができます。ヒントコメントの開始/*+の+とヒントテキストの間にはスペースを入れても入れなくても構いません。コメント内に複数のヒントが含まれる場合、ヒント同士は少なくとも1つのスペースで区切る必要があります。以下の例では、
/*+ hint1 */と/*+ hint3 hint4 */は有効なヒントですが、/*+ hint2 */は無効なヒントです。select /*+ hint1 */ /*+ hint2 */ * from t1, (select /*+ hint3 hint4 */ t2.* from t2, t3) v where t1.c1 = v.c1;ヒントを追加できる複数の位置が存在するクエリでは、クエリ内で複数のヒントセグメントを使用できます。
ヒントにスペルミスや構文エラーが含まれる場合、無視されます。ただし、データベースは同一コメント内で他の正しく指定されたヒントの使用を考慮します。
CREATE、DELETE、INSERT、REPLACE、SELECT、またはUPDATEキーワードの後に続かないヒントは無効です。ヒントの組み合わせが互いに競合する場合、ヒントは無効です。ただし、データベースは同一コメント内で他の競合しないヒントの使用を考慮します。
ヒントはコメントとしてクエリに追加されるため、一部のクライアント/ドライバーがクエリ内のコメントを削除し、ヒントが無効になる可能性があります。
ヒント内でクエリブロックを定義する
多くのヒントでは、オプションのクエリブロック名を定義することで、そのヒントが適用されるクエリブロックを指定できます。詳細については、Query Block Name と QB_NAME ヒントを使用したクエリ最適化の制御を参照してください。
この構文を使用すると、外部クエリで組み込みビューに適用するヒントを指定できます。
クエリブロックパラメータの構文は @queryblock であり、queryblock はクエリ内で指定されたクエリブロックの識別子です。queryblock 識別子はシステム生成のものでも、ユーザーが自ら指定したものでもかまいません。クエリブロック内で直接適用するヒントを指定する場合は、@queryblock は無視されます。
システム生成の識別子は、クエリに
EXPLAINを実行することで生成できます。QB_NAME を使用して、ユーザー定義の名前を指定できます。
ヒントの分類と機能
OceanBaseデータベースのヒントは、主に2つのタイプに分類されます:グローバルヒント(Global Hint)とクエリブロックヒント(Query Block Hint)です。
クエリブロックヒントはさらに、QB_NAMEヒント、トランスフォームヒント、オプティマイザーヒントに細分化され、各ヒントはオプティマイザー内での役割に応じて異なる分類がされます。
グローバルヒント(Global Hint)
グローバルヒントはクエリ全体に作用し、クエリ内での位置に関係なく常に同じ効果を発揮します。例えば、以下の2つのクエリで使用されている並列実行ヒントは等価です:
select /*+ parallel(8) */ * from ( select * from t1);
select * from ( select /*+ parallel(8) */ * from t1);
グローバルヒントの定義
グローバルヒントは特定のテーブルやインデックスに対しても、より広範囲にビュー内のテーブルやインデックスの一部に適用することもできます。tablespec と indexspec を使用して、グローバルヒントの作用対象を定義できます:
tablespec:グローバルヒントが作用するテーブルを定義します。ヒントを使用する際には、クエリステートメントに表示されているテーブル名またはエイリアスに厳密に従う必要があります。クエリでテーブルのエイリアスが使用されている場合、ヒントでも対応するエイリアスを使用する必要があります。[ view.[, view. ]... ] table_name注意:クエリにスキーマ名が含まれていても、ヒントにはスキーマ名を含めないでください。
注意:ANSI接続を使用するクエリでは、
tablespec句で指定されたグローバルヒントは無効です。これは、オプティマイザーが解析プロセスで追加のビューを生成するためです。この場合、@queryblockを使用してクエリブロックのヒントを指定する必要があります。indexspec:グローバルヒントが作用するインデックスを定義します。ヒントを説明する際に、tablespecの後にindexspecを続けることができ、カンマで区切ったテーブル名とインデックス名はオプションです。{ index | ( [ table. ] column_name [ [ table. ] column_name ]... ) }
クエリブロックヒント(Query Block Hint)
OceanBaseオプティマイザーがクエリを解析する際、クエリの構造に基づいて複数のクエリブロックに分割します。各クエリブロックには独自のクエリブロック名(Query Block Name)が付けられます。クエリブロック名はオプティマイザーが自動生成することも、QB_NAMEヒントで明示的に指定することもできます。クエリブロックヒントを使用してヒントの適用範囲や対象を指定する方法など、Query Block NameとQB_NAME Hintの詳細については、Query Block NameとQB_NAME Hintを参照してください。
例えば、以下のクエリでは、外部クエリブロックの名前は qb1、インラインビュー v 内のクエリブロックの名前は qb2 です:
select /*+ qb_name(qb1) */ * from ( select /*+ qb_name(qb2) */ * from t1 ) v;
クエリブロックヒントは特定のクエリブロック内でのみ有効です。クエリブロックヒントを有効にする方法は2つあります:
- ヒントを直接指定したいクエリブロックに追加します。
- ヒント内にクエリブロック名を指定します。構文は
Hint_Name(@qb_name ...)です。
例えば、以下のクエリでは、no_merge ヒントは直接クエリブロック qb2 に追加され、そのブロック内で有効になります。index(@qb2 t1 idx) ヒントはクエリブロック qb1 に追加され、クエリブロック名を指定することでクエリブロック qb2 内で有効になります。
select /*+ index(@qb2 t1 idx) qb_name(qb1) */ *
from ( select /*+ no_merge qb_name(qb2) */ * from t1 ) v;
クエリブロックヒントでは、QB_NAME ヒントが現在のクエリブロックの名前を指定するために使用される以外、他のヒントはオプティマイザーのクエリリライト段階と計画生成段階でそれぞれ機能します。Transform ヒントはクエリのリライト動作に干渉し、Optimizer ヒントは計画生成動作に干渉します。