OceanBaseデータベースのオプティマイザーは、クエリを解析・処理する際に、クエリの構造を複数のクエリブロック(Query Block)に分解します。各ブロックには一意のクエリブロック名(Query Block Name、略称:QB Name)が付与されます。手動で指定しない場合、オプティマイザーが自動的にQB Nameを生成します。
QB_NAME ヒントの構文とルール
QB_NAME ヒントを使用して、クエリブロックにQB Nameを明示的に割り当てることができます。構文は以下のとおりです:
/*+ QB_NAME(qb_name) */
以下の例では、外部クエリブロックは qb1、インラインビュー(ビュー view_1 内)は qb2 と命名されています:
SELECT /*+ QB_NAME(qb1) */ * FROM (SELECT /*+ QB_NAME(qb2) */ * FROM t1) view_1;
使用上の注意点:
- QB Nameは大文字小文字を区別しません。
- QB Nameには特殊文字を含めることはできません。
- QB Nameの最大長は20文字です。
- 同一クエリブロックに複数のQB Nameを割り当てたり、異なるブロックで同じQB Nameを使用したりすることはできません。
クエリブロック名の使用方法
クエリブロックヒントの適用範囲の定義
クエリブロックヒントでは、ヒント内でクエリブロック名を指定することで、その適用範囲を定義できます。
以下の例のように、ヒント index(@qb2 t1 idx) はクエリブロック qb1 内で宣言されていますが、クエリブロック qb2 内で有効になるよう指定されています:
SELECT /*+ INDEX(@qb2 t1 idx) QB_NAME(qb1) */ * FROM (SELECT /*+ NO_MERGE QB_NAME(qb2) */ * FROM t1) view_1;
クエリ内のヒント対象の指定
クエリ内のヒント対象を指定することで、クエリ内のヒントの対象を正確に制御できます。
ヒント内でクエリブロック名を使用することで、対象を正確に指定できます。
以下の例のように、leading ヒントを使用する場合、テーブルのクエリブロック名を明示的に指定しないと、ヒントが無効になる可能性があります:
SELECT /*+ LEADING(t1@sel$1 t1@sel$2) */ * FROM t1, (SELECT * FROM t1) v WHERE t1.c2 = v.c2;
Query Plan
===========================
|ID|OPERATOR |NAME|
---------------------------
|0 |HASH JOIN | |
|1 |├─TABLE FULL SCAN|t1 |
|2 |└─TABLE FULL SCAN|t1 |
===========================
クエリブロック名の自動生成ルール
QB Nameが指定されていない場合、オプティマイザーは以下の形式でクエリブロック名を自動生成します:
query_block_type_str$idx
ここで、query_block_type_str$ はクエリブロックタイプを識別する文字列、idx はそのクエリブロックを識別する番号です。
次の表は、異なるタイプのクエリブロックに自動生成される名前の例を示しています:
クエリブロック |
例 |
|---|---|
| SELECT | SEL$1 |
| UNION ALL/UNION/INTERSECT/MINUS | SET$1 |
| INSERT | INS$1 |
| UPDATE | UPD$1 |
| DELETE | DEL$1 |
| MERGE | MRG$1 |
| REPLACE | REP$1 |
| INSERT ALL | INS_ALL$1 |
以下の例のように、UNION はオプティマイザーに対し、これらの操作を含むクエリブロックに自動的にクエリブロック名を生成するよう指示します。例えば、UNION を使用するクエリでは、そのクエリブロックは自動的に SET$1 と命名されます:
SELECT /*+ USE_HASH_SET(@SET$1) */ c1, c2 FROM t1
UNION
SELECT c1, c2 FROM t2;
この例では、ヒント /*+USE_HASH_SET(@SET$1) */ は、オプティマイザーに UNION 操作に HASH DISTINCT SET アルゴリズムを使用するよう指示します。
複雑なクエリにおけるQuery Block Name
より複雑なクエリを解析する際、オプティマイザーは外側から内側への順序で各クエリブロックに連番を割り当てます。QB_NAME ヒントを手動で指定しない場合、自動生成されるQuery Block Namesは次のとおりです:
SELECT /*+ QB_NAME(qb1) */ * FROM (SELECT /*+ QB_NAME(qb2) */ * FROM t1) v;
QB_NAME ヒントを外した後、外部クエリブロック qb1 の自動生成名は SEL$1 となり、内部ブロック qb2 の名前は SEL$2 となります。
クエリのリライトとQuery Block Nameの変化
クエリブロックがクエリのリライトをトリガーすると、そのQuery Block Nameは変更される可能性があります。EXPLAIN EXTENDED コマンドを使用することで、クエリ計画の qb name trace においてこれらの変化を追跡できます。
クエリのリライト前の自動生成Query Block Nameを確認するには、クエリ内に NO_QUERY_TRANSFORMATION ヒントを含めてすべてのクエリリライトを禁止し、その後 EXPLAIN OUTLINE を使用してOUTLINE DATAを取得します。OUTLINE DATAの FULL、INDEX などのQuery Blockヒントを分析することで、各Query BlockのNameを検証できます。
例えば、このクエリでは OUTLINE DATA の FULL(@"SEL$2" "test"."t1"@"SEL$2") が、インラインビュー v 内のQuery Block Nameが SEL$2 であることを示しています:
SELECT /*+ NO_QUERY_TRANSFORMATION */ COUNT(*)
FROM (SELECT * FROM t1) v GROUP BY c1;