INSERT INTO SELECTは、パラレルDMLなどの前提条件を満たす場合、APPEND、DIRECT(...)、enable_parallel_dmlなどのヒントを使用してダイレクトロードを有効にできます。ヒントを明示的に指定しない場合でも、パラメータdefault_load_modeを設定することでインポート動作を制御できます。
書き込み先と処理方法の違いにより、INSERT INTO SELECTのダイレクトロードはフルダイレクトロードと増分ダイレクトロードに分けられます。フルダイレクトロードは初回ロードやデータの完全上書きシナリオに適しており、増分ダイレクトロードは既存データに対する一括追加シナリオに適しています。以下では、それぞれの方式の制限事項、構文、使用例を紹介します。
フルダイレクトロード
使用上の制限
- ダイレクトロードはPDML(Parallel Data Manipulation Language、並列データ操作言語)のみをサポートしており、非PDMLでは使用できません。並列DMLの詳細については、並列DMLを参照してください。
- インポート中は、2つの書き込み操作文を同時に実行することはできません(つまり、1つのテーブルに同時に書き込むことはできません)。インポートプロセスでは最初にテーブルロックが取得され、インポート全体を通じて読み取り操作のみが可能となるためです。
- ダイレクトロードはDDLステートメントに属するため、複数行トランザクション(複数の操作を含むトランザクション)内での実行はできません。
- BEGIN内での実行はできません。
- Autocommitは1に設定する必要があります。
- トリガー(Trigger)での使用はサポートされていません。
- 生成列を含むテーブルはサポートされていません(一部のインデックスは隠れた生成列を作成する場合があります。例:KEY
idx_c2(c2(16)) GLOBAL)。 - Liboblogやフラッシュバッククエリ(Flashback Query)はサポートされていません。
使用構文
INSERT /*+ [APPEND |DIRECT(need_sort,max_error,'full')] enable_parallel_dml parallel(N) */ INTO table_name [PARTITION(PARTITION_OPTION)] select_sentence
INSERT INTO構文の詳細については、INSERT(MySQLモード)およびINSERT(Oracleモード)を参照してください。
パラメータの説明:
パラメータ |
説明 |
|---|---|
| APPEND | DIRECT() | ヒントを使用してダイレクトロード機能を有効にします。
|
| enable_parallel_dml | データロードの並列度を設定します。
説明通常、 |
| parallel(N) | データロードの並列度を設定します。必須項目で、1より大きい整数を指定します。 |
| table_name | データをインポートするテーブル名を指定します。任意の数の列を指定できます。 |
| PARTITION_OPTION | パーティションダイレクトロード時のパーティション名を指定します:
|
使用例
例1:INSERT INTO SELECTを使用したフルダイレクトロードの完全な使用例。
ダイレクトロードを使用して、テーブル tbl2 の一部のデータをテーブル tbl1 にインポートします。
テーブル
tbl1にデータがあるかどうかを確認します。この時点では、テーブルは空であることが表示されます。obclient [test]> SELECT * FROM tbl1; Empty setテーブル
tbl2にデータがあるかどうかを確認します。obclient [test]> SELECT * FROM tbl2;テーブル
tbl2にデータがあることが確認されました。+------+------+------+ | col1 | col2 | col3 | +------+------+------+ | 1 | a1 | 11 | | 2 | a2 | 22 | | 3 | a3 | 33 | +------+------+------+ 3 rows in setダイレクトロードを使用して、テーブル
tbl2のデータをテーブルtbl1にインポートします。INSERT INTO SELECTステートメントのヒントを指定します。パーティションを指定せずにインポートします。
obclient [test]> INSERT /*+ DIRECT(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl1 SELECT t2.col1,t2.col3 FROM tbl2 t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0(オプション)パーティションを指定してインポートします。
obclient [test]> INSERT /*+ DIRECT(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl1 partition(p0, p1) SELECT t2.col1,1 FROM tbl2 partition(p0, p1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0obclient [test]> INSERT /*+ DIRECT(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl1 partition(p0, p1) SELECT t2.col1,1 FROM tbl2 partition(p0sp0_1, p1sp1_1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0
INSERT INTO SELECTステートメントのヒントを指定しません。パラメータ
default_load_modeの値をFULL_DIRECT_WRITEに設定します。obclient [test]> ALTER SYSTEM SET default_load_mode ='FULL_DIRECT_WRITE';obclient [test]> INSERT INTO tbl1 SELECT t2.col1,t2.col3 FROM tbl1 t2;
テーブル
tbl1にデータがインポートされているかどうかを確認します。obclient [test]> SELECT * FROM tbl1;クエリ結果は次のとおりです:
+------+------+ | col1 | col2 | +------+------+ | 1 | 11 | | 2 | 22 | | 3 | 33 | +------+------+ 3 rows in set結果は、テーブル
tbl1にデータがインポートされたことを示しています。(オプション)
EXPLAIN EXTENDEDステートメントの戻り結果のNoteで、ダイレクトロードによって書き込まれたデータかどうかを確認します。obclient [test]> EXPLAIN EXTENDED INSERT /*+ direct(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl1 SELECT t2.col1,t2.col3 FROM tbl2 t2;戻り結果は次のとおりです:
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ============================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ------------------------------------------------------------------------------ | | |0 |PX COORDINATOR | |3 |27 | | | |1 |└─EXCHANGE OUT DISTR |:EX10001 |3 |27 | | | |2 | └─INSERT | |3 |26 | | | |3 | └─EXCHANGE IN DISTR | |3 |1 | | | |4 | └─EXCHANGE OUT DISTR (RANDOM)|:EX10000 |3 |1 | | | |5 | └─SUBPLAN SCAN |ANONYMOUS_VIEW1|3 |1 | | | |6 | └─PX BLOCK ITERATOR | |3 |1 | | | |7 | └─TABLE FULL SCAN |t2 |3 |1 | | | ============================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output(nil), filter(nil), rowset=16 | | 1 - output(nil), filter(nil), rowset=16 | | dop=16 | | 2 - output(nil), filter(nil) | | columns([{tbl1: ({tbl1: (tbl1.__pk_increment(0x7efa63627790), tbl1.col1(0x7efa63611980), tbl1.col3(0x7efa63611dc0))})}]), partitions(p0), | | column_values([T_HIDDEN_PK(0x7efa63627bd0)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.col1(0x7efa63626f10))(0x7efa63627ff0)], [column_conv(INT, | | PS:(11,0),NULL,ANONYMOUS_VIEW1.col3(0x7efa63627350))(0x7efa6362ff20)]) | | 3 - output([T_HIDDEN_PK(0x7efa63627bd0)], [ANONYMOUS_VIEW1.col1(0x7efa63626f10)], [ANONYMOUS_VIEW1.col3(0x7efa63627350)]), filter(nil), rowset=16 | | 4 - output([T_HIDDEN_PK(0x7efa63627bd0)], [ANONYMOUS_VIEW1.col1(0x7efa63626f10)], [ANONYMOUS_VIEW1.col3(0x7efa63627350)]), filter(nil), rowset=16 | | dop=16 | | 5 - output([ANONYMOUS_VIEW1.col1(0x7efa63626f10)], [ANONYMOUS_VIEW1.col3(0x7efa63627350)]), filter(nil), rowset=16 | | access([ANONYMOUS_VIEW1.col1(0x7efa63626f10)], [ANONYMOUS_VIEW1.col3(0x7efa63627350)]) | | 6 - output([t2.col1(0x7efa63625ed0)], [t2.col3(0x7efa63626780)]), filter(nil), rowset=16 | | 7 - output([t2.col1(0x7efa63625ed0)], [t2.col3(0x7efa63626780)]), filter(nil), rowset=16 | | access([t2.col1(0x7efa63625ed0)], [t2.col3(0x7efa63626780)]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([t2.__pk_increment(0x7efa63656410)]), range(MIN ; MAX)always true | | Used Hint: | | ------------------------------------- | | /*+ | | | | USE_PLAN_CACHE( NONE ) | | PARALLEL(16) | | ENABLE_PARALLEL_DML | | DIRECT(TRUE, 0, 'FULL') | | */ | | Qb name trace: | | ------------------------------------- | | stmt_id:0, stmt_type:T_EXPLAIN | | stmt_id:1, INS$1 | | stmt_id:2, SEL$1 | | Outline Data: | | ------------------------------------- | | /*+ | | BEGIN_OUTLINE_DATA | | PARALLEL(@"SEL$1" "t2"@"SEL$1" 16) | | FULL(@"SEL$1" "t2"@"SEL$1") | | USE_PLAN_CACHE( NONE ) | | PARALLEL(16) | | ENABLE_PARALLEL_DML | | OPTIMIZER_FEATURES_ENABLE('4.3.3.0') | | DIRECT(TRUE, 0, 'FULL') | | END_OUTLINE_DATA | | */ | | Optimization Info: | | ------------------------------------- | | t2: | | table_rows:3 | | physical_range_rows:3 | | logical_range_rows:3 | | index_back_rows:0 | | output_rows:3 | | table_dop:16 | | dop_method:Global DOP | | avaiable_index_name:[tbl2] | | stats info:[version=0, is_locked=0, is_expired=0] | | dynamic sampling level:0 | | estimation method:[DEFAULT, STORAGE] | | Plan Type: | | DISTRIBUTED | | Note: | | Degree of Parallelism is 16 because of hint | | Direct-mode is enabled in insert into select | +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ 77 rows in set (0.009 sec)
例2:Range-Hashサブパーティションテーブルに対して、パーティション単位のダイレクトロードを指定する場合。
ターゲットテーブルはサブパーティションであり、パーティションはRangeパーティション、サブパーティションはHashパーティションです。パーティション単位のフルダイレクトロードを指定します。
2つのパーティションを含むテーブル
tbl1を作成します。パーティションはRangeパーティション、サブパーティションはHashパーティションです。obclient [test]> CREATE TABLE tbl1(col1 INT,col2 INT) PARTITION BY RANGE COLUMNS(col1) SUBPARTITION BY HASH(col2) SUBPARTITIONS 3 ( PARTITION p0 VALUES LESS THAN(10), PARTITION p1 VALUES LESS THAN(20));ダイレクトロードを使用して、テーブル
tbl2のデータをテーブルtbl1のp0、p1パーティションにインポートします。obclient [test]> insert /*+ direct(true, 0, 'full') enable_parallel_dml parallel(3) append */ into tbl1 partition(p0,p1) select * from tbl2 where col1 <20;
例1:INSERT INTO SELECTを使用したフルダイレクトロードの完全な使用例。
ダイレクトロードを使用して、テーブル tbl4 の一部データをテーブル tbl3 にインポートします。
テーブル
tbl3にデータがあるかどうかを確認します。この時点では、テーブルは空であることが表示されます。obclient [test]> SELECT * FROM tbl3; Empty setテーブル
tbl4にデータがあるかどうかを確認します。obclient [test]> SELECT * FROM tbl4;テーブル
tbl4にデータがあることが確認されました。+------+------+------+ | COL1 | COL2 | COL3 | +------+------+------+ | 1 | a1 | 11 | | 2 | a2 | 22 | | 3 | a3 | 33 | +------+------+------+ 3 rows in set (0.000 sec)ダイレクトロードを使用して、テーブル
tbl4のデータをテーブルtbl3にインポートします。INSERT INTO SELECTステートメントのHintを指定します。パーティションを指定せずにインポートします。
obclient [test]> INSERT /*+ direct(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl3 SELECT t2.col1, t2.col3 FROM tbl4 t2 WHERE ROWNUM <= 10000; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0(オプション)パーティションを指定してインポートします。
obclient [test]> INSERT /*+ DIRECT(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl3 partition(p0, p1) SELECT t2.col1,1 FROM tbl4 partition(p0, p1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0obclient [test]> INSERT /*+ DIRECT(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl3 partition(p0, p1) SELECT t2.col1,1 FROM tbl4 partition(p0sp0_1, p1sp1_1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0
INSERT INTO SELECTステートメントのHintを指定しません。パラメータ
default_load_modeの値をFULL_DIRECT_WRITEに設定します。obclient [test]> ALTER SYSTEM SET default_load_mode ='FULL_DIRECT_WRITE';obclient [test]> INSERT INTO tbl3 SELECT t2.col1, t2.col3 FROM tbl4 t2 WHERE ROWNUM <= 10000;
テーブル
tbl3にデータがインポートされているかどうかを検証します。obclient [test]> SELECT * FROM tbl3;クエリ結果は次のとおりです:
+------+------+ | col1 | col3 | +------+------+ | 1 | 11 | | 2 | 22 | | 3 | 33 | +------+------+ 3 rows in set結果は、テーブル
tbl3にデータがインポートされたことを示しています。(オプション)
EXPLAIN EXTENDEDステートメントの実行結果にあるNoteセクションを確認し、ダイレクトロードによって書き込まれたデータかどうかを確認します。obclient [test]> EXPLAIN EXTENDED INSERT /*+ direct(true, 0, 'full') enable_parallel_dml parallel(16) */ INTO tbl3 SELECT t2.col1,t2.col3 FROM tbl4 t2;実行結果は次のとおりです:
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | =================================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ----------------------------------------------------------------------------------- | | |0 |OPTIMIZER STATS MERGE | |3 |29 | | | |1 |└─PX COORDINATOR | |3 |29 | | | |2 | └─EXCHANGE OUT DISTR |:EX10001 |3 |27 | | | |3 | └─INSERT | |3 |27 | | | |4 | └─OPTIMIZER STATS GATHER | |3 |1 | | | |5 | └─EXCHANGE IN DISTR | |3 |1 | | | |6 | └─EXCHANGE OUT DISTR (RANDOM) |:EX10000 |3 |1 | | | |7 | └─SUBPLAN SCAN |ANONYMOUS_VIEW1|3 |1 | | | |8 | └─PX BLOCK ITERATOR | |3 |1 | | | |9 | └─COLUMN TABLE FULL SCAN|T2 |3 |1 | | | =================================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output(nil), filter(nil), rowset=16 | | 1 - output([column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL1(0x7ef8f6027720))(0x7ef8f60287f0)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60))(0x7ef8f6030710)]), filter(nil), rowset=16 | | 2 - output([column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL1(0x7ef8f6027720))(0x7ef8f60287f0)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60))(0x7ef8f6030710)]), filter(nil), rowset=16 | | dop=16 | | 3 - output([column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL1(0x7ef8f6027720))(0x7ef8f60287f0)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60))(0x7ef8f6030710)]), filter(nil) | | columns([{TBL3: ({TBL3: (TBL3.__pk_increment(0x7ef8f6027fa0), TBL3.COL1(0x7ef8f6011d50), TBL3.COL3(0x7ef8f6012190))})}]), partitions(p0), | | column_values([T_HIDDEN_PK(0x7ef8f60283e0)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL1(0x7ef8f6027720))(0x7ef8f60287f0)], [column_conv(NUMBER, | | PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60))(0x7ef8f6030710)]) | | 4 - output([column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL1(0x7ef8f6027720))(0x7ef8f60287f0)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60))(0x7ef8f6030710)], | | [T_HIDDEN_PK(0x7ef8f60283e0)]), filter(nil), rowset=16 | | 5 - output([T_HIDDEN_PK(0x7ef8f60283e0)], [ANONYMOUS_VIEW1.COL1(0x7ef8f6027720)], [ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60)]), filter(nil), rowset=16 | | 6 - output([T_HIDDEN_PK(0x7ef8f60283e0)], [ANONYMOUS_VIEW1.COL1(0x7ef8f6027720)], [ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60)]), filter(nil), rowset=16 | | dop=16 | | 7 - output([ANONYMOUS_VIEW1.COL1(0x7ef8f6027720)], [ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60)]), filter(nil), rowset=16 | | access([ANONYMOUS_VIEW1.COL1(0x7ef8f6027720)], [ANONYMOUS_VIEW1.COL3(0x7ef8f6027b60)]) | | 8 - output([T2.COL1(0x7ef8f60264c0)], [T2.COL3(0x7ef8f6026f90)]), filter(nil), rowset=16 | | 9 - output([T2.COL1(0x7ef8f60264c0)], [T2.COL3(0x7ef8f6026f90)]), filter(nil), rowset=16 | | access([T2.COL1(0x7ef8f60264c0)], [T2.COL3(0x7ef8f6026f90)]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([T2.__pk_increment(0x7ef8f60584a0)]), range(MIN ; MAX)always true | | Used Hint: | | ------------------------------------- | | /*+ | | | | USE_PLAN_CACHE( NONE ) | | PARALLEL(16) | | ENABLE_PARALLEL_DML | | DIRECT(TRUE, 0, 'FULL') | | */ | | Qb name trace: | | ------------------------------------- | | stmt_id:0, stmt_type:T_EXPLAIN | | stmt_id:1, INS$1 | | stmt_id:2, SEL$1 | | Outline Data: | | ------------------------------------- | | /*+ | | BEGIN_OUTLINE_DATA | | PARALLEL(@"SEL$1" "T2"@"SEL$1" 16) | | FULL(@"SEL$1" "T2"@"SEL$1") | | USE_COLUMN_TABLE(@"SEL$1" "T2"@"SEL$1") | | USE_PLAN_CACHE( NONE ) | | PARALLEL(16) | | ENABLE_PARALLEL_DML | | OPTIMIZER_FEATURES_ENABLE('4.3.3.0') | | DIRECT(TRUE, 0, 'FULL') | | END_OUTLINE_DATA | | */ | | Optimization Info: | | ------------------------------------- | | T2: | | table_rows:3 | | physical_range_rows:3 | | logical_range_rows:3 | | index_back_rows:0 | | output_rows:3 | | table_dop:16 | | dop_method:Global DOP | | avaiable_index_name:[TBL4] | | stats info:[version=0, is_locked=0, is_expired=0] | | dynamic sampling level:0 | | estimation method:[DEFAULT, STORAGE] | | Plan Type: | | DISTRIBUTED | | Note: | | Degree of Parallelism is 16 because of hint | +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 82 rows in set (0.006 sec)
例2:Range-Hashサブパーティションテーブルに対して、パーティション単位でダイレクトロードを指定する場合。
ターゲットテーブルはサブパーティションであり、パーティション単位がRangeパーティション、サブパーティション単位がHashパーティションです。パーティション単位でのフルダイレクトロードを指定します。
2つのパーティションを含むテーブル
tbl1を作成します。パーティション単位がRangeパーティション、サブパーティション単位がHashパーティションです。obclient [test]> CREATE TABLE tbl1_1 ( col1 INT, col2 INT ) PARTITION BY RANGE (col1) SUBPARTITION BY HASH (col2) SUBPARTITION TEMPLATE ( SUBPARTITION sp1, SUBPARTITION sp2, SUBPARTITION sp3 ) ( PARTITION p0 VALUES LESS THAN (10), PARTITION p1 VALUES LESS THAN (20) );ダイレクトロードを使用して、テーブル
tbl2のデータをテーブルtbl1のp0、p1パーティションにインポートします。obclient [test]> insert /*+ direct(true, 0, 'full') enable_parallel_dml parallel(3) append */ into tbl1 partition(p0,p1) select * from tbl2 where col1 <20;
増分ダイレクトロード
使用上の制限
- ダイレクトロードはPDML(Parallel Data Manipulation Language、並列データ操作言語)のみをサポートしており、非PDMLでは使用できません。並列DMLの詳細については、並列DMLを参照してください。
- インポート中は、同時に2つの書き込み操作ステートメントを実行することはできません(つまり、1つのテーブルに同時に書き込むことはできません)。インポートプロセスでは最初にテーブルロックが取得され、インポート全体を通じて読み取り操作のみが可能となるためです。
- トリガー(Trigger)での使用はサポートされていません。
- 生成列を含むテーブルはサポートされていません(一部のインデックスは隠れた生成列を作成する場合があります。例:KEY
idx_c2(c2(16)) GLOBAL)。 - Liboblogやフラッシュバッククエリ(Flashback Query)はサポートされていません。
- インデックス(主キーを除く)を持つテーブルは、増分ダイレクトロードをサポートしていません。
- 外部キーを持つテーブルは、増分ダイレクトロードをサポートしていません。
GLOBALインデックスを持つテーブルは、増分ダイレクトロードをサポートしていません。- 制約を持つテーブルは、増分ダイレクトロードをサポートしていません。
- 主キーがなく、複数の
LOCAL唯一インデックスを持つテーブルは、増分ダイレクトロードをサポートしていません。 - 主キーを持ち、唯一インデックスを持つテーブルは、増分ダイレクトロードをサポートしていません。
使用構文
INSERT /*+ [DIRECT(need_sort,max_error,{'inc'|'inc_replace'})] enable_parallel_dml parallel(N) */ INTO table_name [PARTITION(PARTITION_OPTION)] select_sentence
INSERT INTO 構文の詳細については、INSERT(MySQLモード)およびINSERT(Oracleモード)を参照してください。
パラメータの説明:
パラメータ |
説明 |
|---|---|
| DIRECT() | ヒントを使用してダイレクトロード機能を有効にします。DIRECT() パラメータの説明は以下のとおりです:
|
| enable_parallel_dml | データロードの並列度を設定します。
説明通常、 |
| parallel(N) | データロードの並列度を設定します。必須項目で、1より大きい整数を指定します。 |
| table_name | データをインポートするテーブル名を指定します。任意の数の列を指定できます。 |
| PARTITION_OPTION | パーティションダイレクトロード時のパーティション名を指定します:
|
使用例
INSERT INTO SELECT ステートメントを使用した増分ダイレクトロードの操作手順は、フルダイレクトロードと同じです。full フィールドの値を inc または inc_replace に置き換えるだけです。
例1:INSERT INTO SELECTを使用した増分ダイレクトロードの完全な例。
ダイレクトロードを使用して、テーブル tbl2 の一部データをテーブル tbl1 にインポートします。
テーブル
tbl1にデータがあるかどうかを確認します。この時点では、テーブルは空であることが表示されます。obclient [test]> SELECT * FROM tbl1; Empty setテーブル
tbl2にデータがあるかどうかを確認します。obclient [test]> SELECT * FROM tbl2;テーブル
tbl2にデータがあることが確認されました。+------+------+------+ | col1 | col2 | col3 | +------+------+------+ | 1 | a1 | 11 | | 2 | a2 | 22 | | 3 | a3 | 33 | +------+------+------+ 3 rows in setダイレクトロードを使用して、テーブル
tbl2のデータをテーブルtbl1にインポートします。INSERT INTO SELECTステートメントのHintを指定します。パーティションインポートは指定しません。
obclient [test]> INSERT /*+ DIRECT(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl1 SELECT t2.col1,t2.col3 FROM tbl2 t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0(オプション)パーティションインポートを指定します。
obclient [test]> INSERT /*+ DIRECT(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl1 partition(p0, p1) SELECT t2.col1,1 FROM tbl2 partition(p0, p1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0obclient [test]> INSERT /*+ DIRECT(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl1 partition(p0, p1) SELECT t2.col1,1 FROM tbl2 partition(p0sp0_1, p1sp1_1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0
INSERT INTO SELECTステートメントのHintを指定しません。パラメータ
default_load_modeの値をINC_DIRECT_WRITEまたはINC_REPLACE_DIRECT_WRITEに設定します。obclient [test]> ALTER SYSTEM SET default_load_mode ='INC_DIRECT_WRITE';obclient [test]> INSERT INTO tbl1 SELECT t2.col1,t2.col3 FROM tbl1 t2;
テーブル
tbl1にデータがインポートされているかどうかを検証します。obclient [test]> SELECT * FROM tbl1;クエリ結果は次のとおりです:
+------+------+ | col1 | col2 | +------+------+ | 1 | 11 | | 2 | 22 | | 3 | 33 | +------+------+ 3 rows in set結果は、テーブル
tbl1にデータがインポートされたことを示しています。(オプション)
EXPLAIN EXTENDEDステートメントの実行結果のNoteセクションで、ダイレクトロードによって書き込まれたデータかどうかを確認します。obclient [test]> EXPLAIN EXTENDED INSERT /*+ direct(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl1 SELECT t2.col1,t2.col3 FROM tbl2 t2;実行結果は次のとおりです:
+--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Query Plan | +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ | ============================================================================== | | |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| | | ------------------------------------------------------------------------------ | | |0 |PX COORDINATOR | |3 |27 | | | |1 |└─EXCHANGE OUT DISTR |:EX10001 |3 |27 | | | |2 | └─INSERT | |3 |26 | | | |3 | └─EXCHANGE IN DISTR | |3 |1 | | | |4 | └─EXCHANGE OUT DISTR (RANDOM)|:EX10000 |3 |1 | | | |5 | └─SUBPLAN SCAN |ANONYMOUS_VIEW1|3 |1 | | | |6 | └─PX BLOCK ITERATOR | |3 |1 | | | |7 | └─TABLE FULL SCAN |t2 |3 |1 | | | ============================================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output(nil), filter(nil), rowset=16 | | 1 - output(nil), filter(nil), rowset=16 | | dop=16 | | 2 - output(nil), filter(nil) | | columns([{tbl1: ({tbl1: (tbl1.__pk_increment(0x7efa518277d0), tbl1.col1(0x7efa518119c0), tbl1.col3(0x7efa51811e00))})}]), partitions(p0), | | column_values([T_HIDDEN_PK(0x7efa51827c10)], [column_conv(INT,PS:(11,0),NULL,ANONYMOUS_VIEW1.col1(0x7efa51826f50))(0x7efa51828030)], [column_conv(INT, | | PS:(11,0),NULL,ANONYMOUS_VIEW1.col3(0x7efa51827390))(0x7efa5182ff60)]) | | 3 - output([T_HIDDEN_PK(0x7efa51827c10)], [ANONYMOUS_VIEW1.col1(0x7efa51826f50)], [ANONYMOUS_VIEW1.col3(0x7efa51827390)]), filter(nil), rowset=16 | | 4 - output([T_HIDDEN_PK(0x7efa51827c10)], [ANONYMOUS_VIEW1.col1(0x7efa51826f50)], [ANONYMOUS_VIEW1.col3(0x7efa51827390)]), filter(nil), rowset=16 | | dop=16 | | 5 - output([ANONYMOUS_VIEW1.col1(0x7efa51826f50)], [ANONYMOUS_VIEW1.col3(0x7efa51827390)]), filter(nil), rowset=16 | | access([ANONYMOUS_VIEW1.col1(0x7efa51826f50)], [ANONYMOUS_VIEW1.col3(0x7efa51827390)]) | | 6 - output([t2.col1(0x7efa51825f10)], [t2.col3(0x7efa518267c0)]), filter(nil), rowset=16 | | 7 - output([t2.col1(0x7efa51825f10)], [t2.col3(0x7efa518267c0)]), filter(nil), rowset=16 | | access([t2.col1(0x7efa51825f10)], [t2.col3(0x7efa518267c0)]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([t2.__pk_increment(0x7efa51856410)]), range(MIN ; MAX)always true | | Used Hint: | | ------------------------------------- | | /*+ | | | | USE_PLAN_CACHE( NONE ) | | PARALLEL(16) | | ENABLE_PARALLEL_DML | | DIRECT(TRUE, 0, 'INC_REPLACE') | | */ | | Qb name trace: | | ------------------------------------- | | stmt_id:0, stmt_type:T_EXPLAIN | | stmt_id:1, INS$1 | | stmt_id:2, SEL$1 | | Outline Data: | | ------------------------------------- | | /*+ | | BEGIN_OUTLINE_DATA | | PARALLEL(@"SEL$1" "t2"@"SEL$1" 16) | | FULL(@"SEL$1" "t2"@"SEL$1") | | USE_PLAN_CACHE( NONE ) | | PARALLEL(16) | | ENABLE_PARALLEL_DML | | OPTIMIZER_FEATURES_ENABLE('4.3.3.0') | | DIRECT(TRUE, 0, 'INC_REPLACE') | | END_OUTLINE_DATA | | */ | | Optimization Info: | | ------------------------------------- | | t2: | | table_rows:3 | | physical_range_rows:3 | | logical_range_rows:3 | | index_back_rows:0 | | output_rows:3 | | table_dop:16 | | dop_method:Global DOP | | avaiable_index_name:[tbl2] | | stats info:[version=0, is_locked=0, is_expired=0] | | dynamic sampling level:0 | | estimation method:[DEFAULT, STORAGE] | | Plan Type: | | DISTRIBUTED | | Note: | | Degree of Parallelism is 16 because of hint | | Direct-mode is enabled in insert into select | +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ 77 rows in set (0.009 sec)
例2:Range-Hashサブパーティションテーブルに対して、パーティション単位でダイレクトロードを指定する場合。
ターゲットテーブルはサブパーティションであり、パーティション単位はRangeパーティション、サブパーティション単位はHashパーティションです。パーティション単位で増分ダイレクトロードを指定します。
2つのパーティションを含むテーブル
tbl1を作成します。パーティション単位はRangeパーティション、サブパーティション単位はHashパーティションです。obclient [test]> CREATE TABLE tbl1(col1 INT,col2 INT) PARTITION BY RANGE COLUMNS(col1) SUBPARTITION BY HASH(col2) SUBPARTITIONS 3 ( PARTITION p0 VALUES LESS THAN(10), PARTITION p1 VALUES LESS THAN(20));ダイレクトロードを使用して、テーブル
tbl2のデータをテーブルtbl1のp0、p1パーティションにインポートします。obclient [test]> insert /*+ direct(true, 0, 'inc_replace') enable_parallel_dml parallel(3) append */ into tbl1 partition(p0,p1) select * from tbl2 where col1 <20;
例1:INSERT INTO SELECTを使用した増分ダイレクトロードの完全な例。
ダイレクトロードを使用して、テーブル tbl4 の一部データを tbl3 にインポートします。
テーブル
tbl3にデータがあるかどうかを確認します。この時点では、テーブルは空であることが表示されます。obclient [test]> SELECT * FROM tbl3; Empty setテーブル
tbl4にデータがあるかどうかを確認します。obclient [test]> SELECT * FROM tbl4;テーブル
tbl4にデータがあることが確認されました。+------+------+------+ | COL1 | COL2 | COL3 | +------+------+------+ | 1 | a1 | 11 | | 2 | a2 | 22 | | 3 | a3 | 33 | +------+------+------+ 3 rows in set (0.000 sec)ダイレクトロードを使用して、テーブル
tbl4のデータをテーブルtbl3にインポートします。INSERT INTO SELECTステートメントのHintを指定します。パーティションのインポートは指定しません。
obclient [test]> INSERT /*+ direct(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl3 SELECT t2.col1, t2.col3 FROM tbl4 t2 WHERE ROWNUM <= 10000; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0(オプション)パーティションを指定してインポートします。
obclient [test]> INSERT /*+ DIRECT(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl3 partition(p0, p1) SELECT t2.col1,1 FROM tbl4 partition(p0, p1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0obclient [test]> INSERT /*+ DIRECT(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl3 partition(p0, p1) SELECT t2.col1,1 FROM tbl4 partition(p0sp0_1, p1sp1_1) t2; Query OK, 3 rows affected Records: 3 Duplicates: 0 Warnings: 0
INSERT INTO SELECTステートメントのヒントを指定しません。パラメータ
default_load_modeの値をINC_DIRECT_WRITEまたはINC_REPLACE_DIRECT_WRITEに設定します。obclient [test]> ALTER SYSTEM SET default_load_mode ='INC_DIRECT_WRITE';obclient [test]> INSERT INTO tbl3 SELECT t2.col1, t2.col3 FROM tbl4 t2 WHERE ROWNUM <= 10000;
テーブル
tbl3にデータがインポートされているか確認します。obclient [test]> SELECT * FROM tbl3;クエリ結果は次のとおりです:
+------+------+ | col1 | col3 | +------+------+ | 1 | 11 | | 2 | 22 | | 3 | 33 | +------+------+ 3 rows in set結果は、テーブル
tbl3にデータがインポートされたことを示しています。(オプション)
EXPLAIN EXTENDEDステートメントの戻り結果のNoteセクションを確認し、ダイレクトロードによって書き込まれたデータがあるかどうかを確認します。obclient [test]> EXPLAIN EXTENDED INSERT /*+ direct(true, 0, 'inc_replace') enable_parallel_dml parallel(16) */ INTO tbl3 SELECT t2.col1,t2.col3 FROM tbl4 t2 WHERE ROWNUM <= 10000;
実行結果は次のとおりです:
```shell
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ========================================================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------------------------------------------------- |
| |0 |PX COORDINATOR | |3 |34 | |
| |1 |└─EXCHANGE OUT DISTR |:EX10002 |3 |33 | |
| |2 | └─INSERT | |3 |32 | |
| |3 | └─EXCHANGE IN DISTR | |3 |7 | |
| |4 | └─EXCHANGE OUT DISTR (RANDOM) |:EX10001 |3 |7 | |
| |5 | └─MATERIAL | |3 |3 | |
| |6 | └─SUBPLAN SCAN |ANONYMOUS_VIEW1|3 |3 | |
| |7 | └─LIMIT | |3 |3 | |
| |8 | └─EXCHANGE IN DISTR | |3 |3 | |
| |9 | └─EXCHANGE OUT DISTR |:EX10000 |3 |1 | |
| |10| └─LIMIT | |3 |1 | |
| |11| └─PX BLOCK ITERATOR | |3 |1 | |
| |12| └─COLUMN TABLE FULL SCAN|T2 |3 |1 | |
| ========================================================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output(nil), filter(nil), rowset=16 |
| 1 - output(nil), filter(nil), rowset=16 |
| dop=16 |
| 2 - output(nil), filter(nil) |
| columns([{TBL3: ({TBL3: (TBL3.__pk_increment(0x7efaad22b0e0), TBL3.COL1(0x7efaad2123f0), TBL3.COL3(0x7efaad212830))})}]), partitions(p0), |
| column_values([T_HIDDEN_PK(0x7efaad22b520)], [column_conv(NUMBER,PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL1(0x7efaad22a860))(0x7efaad22b930)], [column_conv(NUMBER, |
| PS:(-1,0),NULL,ANONYMOUS_VIEW1.COL3(0x7efaad22aca0))(0x7efaad233850)]) |
| 3 - output([T_HIDDEN_PK(0x7efaad22b520)], [ANONYMOUS_VIEW1.COL1(0x7efaad22a860)], [ANONYMOUS_VIEW1.COL3(0x7efaad22aca0)]), filter(nil), rowset=16 |
| 4 - output([T_HIDDEN_PK(0x7efaad22b520)], [ANONYMOUS_VIEW1.COL1(0x7efaad22a860)], [ANONYMOUS_VIEW1.COL3(0x7efaad22aca0)]), filter(nil), rowset=16 |
| is_single, dop=1 |
| 5 - output([ANONYMOUS_VIEW1.COL1(0x7efaad22a860)], [ANONYMOUS_VIEW1.COL3(0x7efaad22aca0)]), filter(nil), rowset=16 |
| 6 - output([ANONYMOUS_VIEW1.COL1(0x7efaad22a860)], [ANONYMOUS_VIEW1.COL3(0x7efaad22aca0)]), filter(nil), rowset=16 |
| access([ANONYMOUS_VIEW1.COL1(0x7efaad22a860)], [ANONYMOUS_VIEW1.COL3(0x7efaad22aca0)]) |
| 7 - output([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), filter(nil), rowset=16 |
| limit(cast(FLOOR(cast(10000, NUMBER(-1, -85))(0x7efaad227ef0))(0x7efaad25ac30), BIGINT(-1, 0))(0x7efaad25b6d0)), offset(nil) |
| 8 - output([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), filter(nil), rowset=16 |
| 9 - output([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), filter(nil), rowset=16 |
| dop=16 |
| 10 - output([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), filter(nil), rowset=16 |
| limit(cast(FLOOR(cast(10000, NUMBER(-1, -85))(0x7efaad227ef0))(0x7efaad25ac30), BIGINT(-1, 0))(0x7efaad25b6d0)), offset(nil) |
| 11 - output([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), filter(nil), rowset=16 |
| 12 - output([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), filter(nil), rowset=16 |
| access([T2.COL1(0x7efaad229470)], [T2.COL3(0x7efaad229f40)]), partitions(p0) |
| limit(cast(FLOOR(cast(10000, NUMBER(-1, -85))(0x7efaad227ef0))(0x7efaad25ac30), BIGINT(-1, 0))(0x7efaad25b6d0)), offset(nil), is_index_back=false, |
| is_global_index=false, |
| range_key([T2.__pk_increment(0x7efaad25a720)]), range(MIN ; MAX)always true |
| Used Hint: |
| ------------------------------------- |
| /*+ |
| |
| USE_PLAN_CACHE( NONE ) |
| PARALLEL(16) |
| ENABLE_PARALLEL_DML |
| DIRECT(TRUE, 0, 'INC_REPLACE') |
| */ |
| Qb name trace: |
| ------------------------------------- |
| stmt_id:0, stmt_type:T_EXPLAIN |
| stmt_id:1, INS$1 |
| stmt_id:2, SEL$1 |
| stmt_id:3, parent:SEL$1 > SEL$658037CB > SEL$DCAFFB86 |
| Outline Data: |
| ------------------------------------- |
| /*+ |
| BEGIN_OUTLINE_DATA |
| PARALLEL(@"SEL$DCAFFB86" "T2"@"SEL$1" 16) |
| FULL(@"SEL$DCAFFB86" "T2"@"SEL$1") |
| USE_COLUMN_TABLE(@"SEL$DCAFFB86" "T2"@"SEL$1") |
| MERGE(@"SEL$658037CB" < "SEL$1") |
| USE_PLAN_CACHE( NONE ) |
| PARALLEL(16) |
| ENABLE_PARALLEL_DML |
| OPTIMIZER_FEATURES_ENABLE('4.3.3.0') |
| DIRECT(TRUE, 0, 'INC_REPLACE') |
| END_OUTLINE_DATA |
| */ |
| Optimization Info: |
| ------------------------------------- |
| T2: |
| table_rows:3 |
| physical_range_rows:3 |
| logical_range_rows:3 |
| index_back_rows:0 |
| output_rows:3 |
| table_dop:16 |
| dop_method:Global DOP |
| avaiable_index_name:[TBL4] |
| stats info:[version=0, is_locked=0, is_expired=0] |
| dynamic sampling level:0 |
| estimation method:[DEFAULT, STORAGE] |
| Plan Type: |
| DISTRIBUTED |
| Note: |
| Degree of Parallelism is 16 because of hint |
| Direct-mode is enabled in insert into select |
| Expr Constraints: |
| cast(FLOOR(cast(10000, NUMBER(-1, -85))), BIGINT(-1, 0)) >= 1 result is TRUE |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
96 rows in set (0.007 sec)
```
例2:Range-Hashサブパーティションテーブルに対して、パーティション単位でデータをダイレクトロードします。
ターゲットテーブルはサブパーティションであり、パーティション単位がRangeパーティション、サブパーティション単位がHashパーティションです。パーティション単位で増分データをダイレクトロードします。
- 2つのパーティションを含むテーブル
tbl1を作成します。パーティション単位がRangeパーティション、サブパーティション単位がHashパーティションです。
obclient [test]> CREATE TABLE tbl1_1 (
col1 INT,
col2 INT
)
PARTITION BY RANGE (col1)
SUBPARTITION BY HASH (col2)
SUBPARTITION TEMPLATE (
SUBPARTITION sp1,
SUBPARTITION sp2,
SUBPARTITION sp3
)
(
PARTITION p0 VALUES LESS THAN (10),
PARTITION p1 VALUES LESS THAN (20)
);
- ダイレクトロードを使用して、テーブル
tbl2のデータをテーブルtbl1のp0、p1パーティションにインポートします。
obclient [test]> insert /*+ direct(true, 0, 'inc_replace') enable_parallel_dml parallel(3) append */ into tbl1 partition(p0,p1) select * from tbl2 where col1 <20;