本記事では、OceanBaseデータベースにおけるHINTの使用規範について説明します。
HINTは慎重に使用し、関連するテーブルの統計情報を収集し、HINTなしでステートメントを評価した後にのみ使用を検討してください。データベース条件の変更や今後のバージョンでのクエリパフォーマンスの向上により、コード内のHINTがパフォーマンスに大きな影響を与える可能性があります。
HINTの概要
コストベースのオプティマイザーであり、OracleのHINTと類似しています。
サーバー側がSQLステートメント内のHINTを認識できない場合、エラーを報告せずに直接無視されます。
HINTはデータベースオプティマイザーが計画を生成するロジックにのみ影響を与え、SQLステートメント自体の意味には影響しません。
HINTは、オプティマイザーに特定の計画を生成させるための仕組みです。通常、オプティマイザーはユーザーのクエリに対して最適な実行計画を選択するため、ユーザーがHINTで指定する必要はありません。しかし、特定のシナリオでは、オプティマイザーが生成する実行計画がユーザーの要件を満たさない場合があります。そのような場合、ユーザーはHINTを使用して、特定の実行計画の生成を明示的に指定する必要があります。
HINT構文
{CREATE|DELETE|INSERT|SELECT|UPDATE|REPLACE} /*+ [HINT_text][hin_text]... */
一つのステートメントブロックには、HINTを含むコメントが1つしか存在できません。また、そのコメントはSELECT、UPDATE、INSERT、MERGE、またはDELETEキーワードの後に続く必要があります。
構文的には、HINTは特殊なSQLコメントですが、コメントの左側のマーカー(
'/*'記号)の後に'+'が追加されています。コメントである以上、サーバー側がSQLステートメント内のHINTを認識できない場合、オプティマイザーはユーザーのHINTを無視し、デフォルトの計画生成ロジックを使用することを選択します。また、HINTはオプティマイザーが計画を生成するロジックにのみ影響を与え、SQLステートメントの意味には影響しない点に注意する必要があります。HINTを定義する際に注意が必要なルール:
プラス記号
'+'により、データベースはコメントをHINTリストとして解釈します。プラス記号はコメントの左側のマーカーの直後に続けて記述する必要があり、スペースは許容されません。プラス記号
'+'とHINTテキストの間のスペースはオプションです。コメントに複数のHINTが含まれる場合、HINT同士は少なくとも1つのスペースまたはカンマで区切る必要があります。スペルミスや構文エラーが含まれる場合は無視されます。ただし、データベースは同一コメント内で他に正しく指定されたHINTを考慮します。
DELETE、INSERT、MERGE、SELECT、またはUPDATEキーワードの後に続かないHINTは無効です。
OceanBaseとOracleでは、HINTの概念が一致しない点以外に、以下の違いがあります:
- Oracleのleading HINTでは、存在しないテーブルが出現した場合、HINTが有効かどうかが推定され、動作が不安定になります。場合によっては有効であり、場合によってはすべて無効になります。
HINTの使用例
パラメータなしの例:
/*+ KAKA */。パラメータを含む場合、例えば
/*+ HAHA(param) */のようにします。複数のHINTは同じコメント内に記述でき、カンマまたは少なくとも1つのスペースで区切ります。例:
/*+ KAKA, HAHA(param)*/。SELECT文のHINTは、キーワードSELECTの直後、他の語の前に配置する必要があります。例:
SELECT /*+ KAKA */。UPDATE、DELETE文のHINTは、キーワードUPDATE、DELETEの直後に配置する必要があります。例:
UPDATE /*+ KAKA */、DELETE /*+ KAKA */。
よく使われるHINTタイプ
Hint名 |
Hintパラメータ |
Hintの意味 |
|---|---|---|
| NO_REWRITE | SQLを再構成しない。 | |
| READ_CONSISTENCY | weak|strong|frozen | weak:弱い一貫性読み取り strong:強い一貫性読み取り frozen:最後のフリーズポイントのデータを読み取る |
| INDEX_HINT | [ qb_name ] table_nameindex_name | クエリテーブル指定時に選択するインデックスを指定します。 |
| QUERY_TIMEOUT | int64 | ステートメント実行のタイムアウト時間を指定します。単位はマイクロ秒(us)です。 |
| LEADING | [ qb_name ] table_name [, table_name ] | 複数テーブル結合時の順序を指定します。 |
| ORDERED | 複数テーブル結合の順序をSQLに登場するテーブルの順に指定します。 | |
| FULL | [qb_name] table_name | テーブルへのアクセス方式をフルテーブルスキャンとして指定します(主キーがある場合は主キーを読み取ります)。 |
| USE_MERGE | [qb_name] table_name [,table_name] | 複数テーブル結合時にMERGEアルゴリズムを使用することを指定します。 |
| USE_NL | [ qb_name ] table_name [, table_name] | 複数テーブル結合時にNEST LOOPアルゴリズムを使用することを指定します。 |
| USE_BNL | [qb_name] table_name [,table_name] | 複数テーブル結合時にBLOCK NEST LOOPアルゴリズムを適用することを指定します。 |
| USE_HASH_AGGREGATION | [ qb_name] | aggregateメソッドでHASH AGGREGATEを使用することを指定します。例:HASH GROUP BY、HASH DISTINCT。 |
| NO_USE_HASH_AGGREGATION | [ qb_name ] | aggregateメソッドでHASH AGGREGATEを使用せず、MERGE GROUP BY、MERGE DISTINCTを使用することを指定します。 |
| QB_NAME | [ qb_name] | query blockの名前を指定します。 |
| PARALLEL | int64 | 分散実行の並列度を指定します。 |
| DISABLE_TRIGGER | trigger_name | DMLで指定されたトリガーを無効にするために使用します。 |
その他のhint関連情報については、SQLチューニングガイドを参照してください。