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;