集合演算に関する動作を制御するHintです。
集合演算句には直接Hintを追加する場所がないため、本記事で紹介するHintはqb nameを使用して対象となる集合演算オブジェクトを指定する必要があります。詳細な使い方については、各Hintの例を参照してください。
| ヒントタイプ | 説明 |
|---|---|
PQ_SET |
集合演算の分散実行方式を制御します。 |
USE_HASH_SET |
オプティマイザーが集合演算でHASHメソッドを使用するようにします。その逆操作はNO_USE_HASH_SETです。 |
NO_USE_HASH_SET |
オプティマイザーが集合演算でHASHメソッドを使用することを禁止します。その逆操作はUSE_HASH_SETです。 |
PQ_SET ヒント
PQ_SET ヒントは、分散実行時の集合演算におけるデータ配布方式を指定します。
構文
PQ_SET ( [ @qb_name ] [left_branch_qb_name] method_list )
パラメータの説明
left_branch_qb_name:UNIONまたはINTERSECT集合演算の左側の部分を決定するために使用されます。method_listは、具体的な分散実行方式を制御します。
具体的な方法と例は以下のとおりです:
| データ配布方式 | outline data hintの説明 | 説明 |
|---|---|---|
| DIST_BASIC_METHOD | PQ_SET ( @SET$1 )、outlineにhintを追加しない | |
| DIST_PARTITION_WISE | PQ_SET ( @SET$1 NONE NONE) | |
| DIST_PULL_TO_LOCAL | PQ_SET ( @SET$1 LOCAL LOCAL) | |
| DIST_SET_RANDOM | PQ_SET ( @SET$1 RANDOM NONE) | UNION ALLに限定 |
| DIST_SET_RANDOM | PQ_SET ( @SET$1 NONE RANDOM) | UNION ALLに限定 |
| DIST_SET_RANDOM | PQ_SET ( @SET$1 RANDOM NONE RANDOM) | UNION ALLに限定 |
| DIST_HASH_HASH | PQ_SET ( @SET$1 SEL$1 HASH HASH) | 二つのブランチのunion/intersectに限定し、SEL$1を左側のブランチとする |
| DIST_NONE_PARTITION | PQ_SET ( @SET$1 SEL$2 NONE PARTITION ) | 二つのブランチのunion/intersectに限定し、SEL$2を左側のブランチとする |
| DIST_PARTITION_NONE | PQ_SET ( @SET$1 SEL$1 PARTITION NONE ) | 二つのブランチのunion/intersectに限定し、SEL$1を左側のブランチとする |
例
以下のクエリ例では、pq_set(@set$1 local local) を使用してデータを直接ローカルにプルバックする分散実行方式を指定し、pq_set(@set$1 sel$2 hash hash) を使用して HASH 方式でデータを再分散して集合演算を行い、sel$2 を集合演算の左側の要素として使用します。
-- PQ_SET ヒントを使用して、集合演算で特定の分散実行方式を指定する
CREATE TABLE tp1(c1 INT, c2 INT, c3 INT) PARTITION BY HASH(c1) PARTITIONS 10;
EXPLAIN BASIC SELECT /*+ PQ_SET(@set$1 local local) */ c2, c3 FROM tp1 a UNION SELECT c2, c3 FROM tp1 b;
+------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------+
| ========================================= |
| |ID|OPERATOR |NAME | |
| ----------------------------------------- |
| |0 |HASH UNION DISTINCT | | |
| |1 |├─PX COORDINATOR | | |
| |2 |│ └─EXCHANGE OUT DISTR |:EX10000| |
| |3 |│ └─PX PARTITION ITERATOR| | |
| |4 |│ └─TABLE FULL SCAN |A | |
| |5 |└─PX COORDINATOR | | |
| |6 | └─EXCHANGE OUT DISTR |:EX20000| |
| |7 | └─PX PARTITION ITERATOR| | |
| |8 | └─TABLE FULL SCAN |B | |
| ========================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([UNION([1])], [UNION([2])]), filter(nil), rowset=16 |
| 1 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| 2 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| dop=1 |
| 3 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| force partition granule |
| 4 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| access([A.C2], [A.C3]), partitions(p[0-9]) |
| is_index_back=false, is_global_index=false, |
| range_key([A.__pk_increment]), range(MIN ; MAX)always true |
| 5 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| 6 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| dop=1 |
| 7 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| force partition granule |
| 8 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| access([B.C2], [B.C3]), partitions(p[0-9]) |
| is_index_back=false, is_global_index=false, |
| range_key([B.__pk_increment]), range(MIN ; MAX)always true |
+------------------------------------------------------------------+
34 rows in set
EXPLAIN BASIC
SELECT /*+ PQ_SET(@set$1 sel$2 hash hash) */ c2, c3 FROM tp1 a
UNION
SELECT c2, c3 FROM tp1 b;
+-----------------------------------------------------------------------------------+
| Query Plan |
+-----------------------------------------------------------------------------------+
| =============================================== |
| |ID|OPERATOR |NAME | |
| ----------------------------------------------- |
| |0 |PX COORDINATOR | | |
| |1 |└─EXCHANGE OUT DISTR |:EX10002| |
| |2 | └─HASH UNION DISTINCT | | |
| |3 | ├─EXCHANGE IN DISTR | | |
| |4 | │ └─EXCHANGE OUT DISTR (HASH)|:EX10000| |
| |5 | │ └─PX PARTITION ITERATOR | | |
| |6 | │ └─TABLE FULL SCAN |B | |
| |7 | └─EXCHANGE IN DISTR | | |
| |8 | └─EXCHANGE OUT DISTR (HASH)|:EX10001| |
| |9 | └─PX PARTITION ITERATOR | | |
| |10| └─TABLE FULL SCAN |A | |
| =============================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(UNION([1]), UNION([2]))]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(UNION([1]), UNION([2]))]), filter(nil), rowset=16 |
| dop=1 |
| 2 - output([UNION([1])], [UNION([2])]), filter(nil), rowset=16 |
| 3 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| 4 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| (#keys=2, [B.C2], [B.C3]), dop=1 |
| 5 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| force partition granule |
| 6 - output([B.C2], [B.C3]), filter(nil), rowset=16 |
| access([B.C2], [B.C3]), partitions(p[0-9]) |
| is_index_back=false, is_global_index=false, |
| range_key([B.__pk_increment]), range(MIN ; MAX)always true |
| 7 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| 8 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| (#keys=2, [A.C2], [A.C3]), dop=1 |
| 9 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| force partition granule |
| 10 - output([A.C2], [A.C3]), filter(nil), rowset=16 |
| access([A.C2], [A.C3]), partitions(p[0-9]) |
| is_index_back=false, is_global_index=false, |
| range_key([A.__pk_increment]), range(MIN ; MAX)always true |
+-----------------------------------------------------------------------------------+
39 rows in set
USE_HASH_SET ヒント
USE_HASH_SET ヒントは、集合演算で使用する具体的なアルゴリズムを制御します。その逆操作は NO_USE_HASH_SET です。
構文
/*+ USE_HASH_SET [ ( [ @ qb_name ] ) ] */
例
以下のクエリ例では、USE_HASH_SET ヒントを使用して HASH アルゴリズムを有効にします。
-- USE_HASH_SETヒントを使用して、集合演算でHASHメソッドを強制的に使用する
EXPLAIN BASIC
SELECT /*+ USE_HASH_SET(@set$1) */ c1, c2, c3 FROM t1
UNION
SELECT c1, c2, c3 FROM t1;
+--------------------------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------------------------+
| ============================= |
| |ID|OPERATOR |NAME| |
| ----------------------------- |
| |0 |HASH UNION DISTINCT| | |
| |1 |├─TABLE FULL SCAN |T1 | |
| |2 |└─TABLE FULL SCAN |T1 | |
| ============================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([UNION([1])], [UNION([2])], [UNION([3])]), filter(nil), rowset=16 |
| 1 - output([T1.C1], [T1.C2], [T1.C3]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2], [T1.C3]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
| 2 - output([T1.C1], [T1.C2], [T1.C3]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2], [T1.C3]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+--------------------------------------------------------------------------------+
18 rows in set
NO_USE_HASH_SET ヒント
NO_USE_HASH_SET ヒントは、集合演算で使用する具体的なアルゴリズムを制御します。その逆操作は USE_HASH_SET です。
構文
/*+ NO_USE_HASH_SET [ ( [ @ qb_name ] ) ] */
例
以下のクエリ例では、NO_USE_HASH_SET を使用してHASHアルゴリズムを禁止します。OceanBaseはHASHとMERGEの2種類の集合演算アルゴリズムをサポートしているため、NO_USE_HASH_SET ヒントを使用すると、実際には集合演算で MERGE アルゴリズムが使用されます。UNION ALL 集合演算は重複除去の意味を持たないため、このヒントによって制御されません。
-- NO_USE_HASH_SETヒントを使用して、オプティマイザーに集合演算でHASHメソッドを使用しないよう指示します
EXPLAIN BASIC
SELECT /*+ NO_USE_HASH_SET(@set$1) */ c1, c2, c3 FROM t1
UNION
SELECT c1, c2, c3 FROM t1;
+--------------------------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------------------------+
| ============================== |
| |ID|OPERATOR |NAME| |
| ------------------------------ |
| |0 |MERGE UNION DISTINCT| | |
| |1 |├─SORT | | |
| |2 |│ └─TABLE FULL SCAN |T1 | |
| |3 |└─SORT | | |
| |4 | └─TABLE FULL SCAN |T1 | |
| ============================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([UNION([1])], [UNION([2])], [UNION([3])]), filter(nil), rowset=16 |
| 1 - output([T1.C1], [T1.C2], [T1.C3]), filter(nil), rowset=16 |
| sort_keys([T1.C1, ASC], [T1.C2, ASC], [T1.C3, ASC]) |
| 2 - output([T1.C1], [T1.C2], [T1.C3]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2], [T1.C3]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
| 3 - output([T1.C1], [T1.C2], [T1.C3]), filter(nil), rowset=16 |
| sort_keys([T1.C1, ASC], [T1.C2, ASC], [T1.C3, ASC]) |
| 4 - output([T1.C1], [T1.C2], [T1.C3]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2], [T1.C3]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+--------------------------------------------------------------------------------+
24 rows in set