本記事では、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を含むコメントは一つしか存在できず、そのコメントはSELECT、UPDATE、INSERT、MERGE、またはDELETEキーワードの後に続く必要があります。
構文的には、HINTは特殊なSQLコメントですが、コメントの左マーカー(
'/*'記号)の後に'+'が追加されている点が異なります。コメントである以上、サーバー側がSQL文内のHINTを認識できない場合、オプティマイザーはユーザーのHINTを無視してデフォルトの計画生成ロジックを使用します。また、HINTはオプティマイザーが計画を生成するロジックにのみ影響し、SQL文の意味には影響しないことを明確にしておく必要があります。HINTを定義する際に注意すべきいくつかのルール:
プラス記号
'+'は、データベースがコメントをHINTリストとして解釈するようにします。プラス記号はコメントの左マーカーの直後に続ける必要があり、スペースは許可されません。プラス記号
'+'とHINTテキストの間のスペースは省略可能です。コメント内に複数のHINTが含まれる場合、HINT同士は少なくとも一つのスペースまたはカンマで区切る必要があります。スペルミスや構文エラーが含まれている場合は無視されます。ただし、同一コメント内で他の正しく指定されたHINTは考慮されます。
DELETE、INSERT、MERGE、SELECT、またはUPDATEキーワードの後に続かないHINTは無効です。
OceanBaseとOracleは、HINTの概念において一致していない点があり、その他にも以下の違いがあります:
- Oracleのleading HINTでは、存在しないテーブルが出現した場合、HINTが有効かどうかを推測するため、動作が不確定になります。一部のケースでは有効であり、一部のケースではすべて無効になります。
HINTの使用例
パラメータなしの例:
/*+ KAKA */。パラメータ付きの例:
/*+ HAHA(param) */。複数のHINTは同一のコメント内に記述でき、カンマまたは少なくとも一つのスペースで区切ります。例:
/*+ KAKA, HAHA(param)*/。SELECT文のHINTは、キーワードSELECTの直後、他の語句の前に記述する必要があります。例:
SELECT /*+ KAKA */。UPDATE、DELETE文のHINTは、キーワードUPDATE、DELETEの直後に記述する必要があります。例:
UPDATE /*+ KAKA */、DELETE /*+ KAKA */。
よく使われる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] | クエリブロックの名前を指定します。 |
| PARALLEL | int64 | 分散実行の並列度を指定します。 |
その他のHINT関連の内容については、SQLチューニングガイドを参照してください。