INSERT 演算子は、指定されたデータをテーブルに挿入するために使用されます。データ源としては、直接指定された値とサブクエリの結果が含まれます。
OceanBaseデータベースでサポートされている INSERT 演算子には、通常の INSERT と DISTRIBUTED INSERT の2種類があります。
通常の INSERT
通常の INSERT は、データテーブルの単一パーティションにデータを挿入するために使用されます。
以下の例のように、Q1 クエリは値 (1, '100') を非パーティションテーブル t1 に挿入します。ここで、1 番目の演算子 EXPRESSION は定数式の値を生成するために使用されます。
--Oracleモード:
obclient> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR2(10));
Query OK, 0 rows affected
obclient> CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 VARCHAR2(10)) PARTITION BY HASH(c1) PARTITIONS 10;
Query OK, 0 rows affected
obclient> CREATE TABLE t3 (c1 INT PRIMARY KEY, c2 VARCHAR2(10));
Query OK, 0 rows affected
obclient> CREATE INDEX IDX_t3_c2 ON t3 (c2) PARTITION BY HASH(c2) PARTITIONS 3;
Query OK, 0 rows affected
--MySQLモード:
obclient> CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT);
Query OK, 0 rows affected
obclient> CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT) PARTITION BY HASH(c1) PARTITIONS 10;
Query OK, 0 rows affected
obclient> CREATE TABLE t3 (c1 INT PRIMARY KEY, c2 INT);
Query OK, 0 rows affected
obclient> CREATE INDEX IDX_t3_c2 ON t3 (c2) PARTITION BY HASH(c2) PARTITIONS 3;
Query OK, 0 rows affected
Q1:
obclient> EXPLAIN INSERT INTO t1 VALUES (1, '100');
Query Plan:
====================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
------------------------------------
|0 |INSERT | |1 |1 |
|1 | EXPRESSION| |1 |1 |
====================================
Outputs & filters:
-------------------------------------
0 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,__values.C1)], [column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,__values.C2)]), filter(nil),
columns([{T1: ({T1: (T1.C1, T1.C2)})}]), partitions(p0)
1 - output([__values.C1], [__values.C2]), filter(nil)
values({1, '100'})
上記の例では、実行計画表示の outputs & filters が INSERT 演算子の出力情報を詳細に示しています:
情報名 |
意味 |
|---|---|
| output | この演算子が出力する式。 |
| filter | この演算子のフィルター条件。例では INSERT 演算子に filter が設定されていないため、nil となります。 |
| columns | 挿入操作に関連するデータテーブルの列。 |
| partitions | 挿入操作に関連するデータテーブルのパーティション(パーティションテーブルでない場合は、1つのパーティションしか持たないパーティションテーブルと見なすことができます)。 |
その他の INSERT 演算子の例:
Q2 クエリは値 (2, '200')、(3, '300') をテーブル
t1に挿入します。Q2: obclient> EXPLAIN INSERT INTO t1 VALUES (2, '200'),(3, '300'); Query Plan: ==================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ------------------------------------ |0 |INSERT | |2 |1 | |1 | EXPRESSION| |2 |1 | ==================================== Outputs & filters: ------------------------------------- 0 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,__values.C1)], [column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,__values.C2)]), filter(nil), columns([{T1: ({T1: (T1.C1, T1.C2)})}]), partitions(p0) 1 - output([__values.C1], [__values.C2]), filter(nil) values({2, '200'}, {3, '300'})Q3 クエリは、サブクエリ
SELECT * FROM t3の結果をテーブルt1に挿入します。Q3: obclient> EXPLAIN INSERT INTO t1 SELECT * FROM t3; Query Plan: ==================================== |0 |INSERT | |100000 |117862| |1 | EXCHANGE IN DISTR | |100000 |104060| |2 | EXCHANGE OUT DISTR| |100000 |75662 | |3 | SUBPLAN SCAN |VIEW1|100000 |75662 | |4 | TABLE SCAN |T3 |100000 |61860 | ================================================ Outputs & filters: ------------------------------------- 0 - output([VIEW1.C1], [VIEW1.C2]), filter(nil), columns([{T1: ({T1: (T1.C1, T1.C2)})}]), partitions(p0) 1 - output([VIEW1.C1], [VIEW1.C2]), filter(nil) 2 - output([VIEW1.C1], [VIEW1.C2]), filter(nil) 3 - output([VIEW1.C1], [VIEW1.C2]), filter(nil), access([VIEW1.C1], [VIEW1.C2]) 4 - output([T3.C1], [T3.C2]), filter(nil), access([T3.C2], [T3.C1]), partitions(p0)Q4 クエリは値 (1, '100') をパーティションテーブル
t2に挿入します。partitionsパラメータから、この値がt2のp5パーティションに挿入されることがわかります。Q4: obclient> EXPLAIN INSERT INTO t2 VALUES (1, '100'); Query Plan: ==================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ------------------------------------ |0 |INSERT | |1 |1 | |1 | EXPRESSION| |1 |1 | ==================================== Outputs & filters: ------------------------------------- 0 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,__values.C1)], [column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,__values.C2)]), filter(nil), columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p5) 1 - output([__values.C1], [__values.C2]), filter(nil) values({1, '100'})
DISTRIBUTED INSERT
DISTRIBUTED INSERTは、データテーブルの複数のパーティションにデータを挿入するために使用されます。
以下の例のように、Q5クエリは値(2, '200')と(3, '300')をパーティションテーブルt2に挿入します。partitionsからわかるように、これらの値はt2のp0およびp6パーティションに挿入されます。
Q5:
obclient> EXPLAIN INSERT INTO t2 VALUES (2, '200'),(3, '300');
Query Plan:
===============================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
-----------------------------------------------
|0 |DISTRIBUTED INSERT| |2 |1 |
|1 | EXPRESSION | |2 |1 |
===============================================
Outputs & filters:
-------------------------------------
0 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,__values.C1)], [column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,__values.C2)]), filter(nil),
columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p0, p6)
1 - output([__values.C1], [__values.C2]), filter(nil)
values({2, '200'}, {3, '300'})
上記の例の実行計画表示におけるoutputs & filtersは、DISTRIBUTED INSERT演算子の情報を詳細に示しています。フィールドの意味はINSERT演算子と同じです。
その他のDISTRIBUTED INSERT演算子の例:
Q6クエリは、サブクエリ
SELECT * FROM t3の結果をパーティションテーブルt2に挿入します。サブクエリの結果セットが不確定なため、データはt2のp0からp9までのいずれかのパーティションに挿入される可能性があります。3番目の演算子からわかるように、ここではSELECT * FROM t3がサブクエリとして配置され、サブクエリにVIEW1という名前が付けられます。OceanBaseデータベースがSQLを内部でリライトしてサブクエリを生成すると、自動的にサブクエリに名前を付け、サブクエリが生成される順序に従ってVIEW1、VIEW2、VIEW3...と命名します。Q6: obclient> EXPLAIN INSERT INTO t2 SELECT * FROM t3; Query Plan: ============================================== |ID|OPERATOR |NAME |EST. ROWS|COST | --------------------------------------------- |0 |DISTRIBUTED INSERT| |100000 |41687| |1 | SUBPLAN SCAN |VIEW1|100000 |40184| |2 | TABLE SCAN |T3 |100000 |38681| ============================================= Outputs & filters: ------------------------------------- 0 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,VIEW1.C1)], [column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,VIEW1.C2)]), filter(nil), columns([{T2: ({T2: (T2.C1, T2.C2)})}]), partitions(p[0-9]) 1 - output([VIEW1.C1], [VIEW1.C2]), filter(nil), access([VIEW1.C1], [VIEW1.C2]) 2 - output([T3.C1], [T3.C2]), filter(nil), access([T3.C2], [T3.C1]), partitions(p0)Q7クエリは、値(1, '100')を非パーティションテーブル
t3に挿入します。t3自体は非パーティションテーブルですが、t3にグローバルインデックスidx_t3_c2が存在するため、この挿入も複数のパーティションに関わります。Q7: obclient> EXPLAIN INSERT INTO t3 VALUES (1, '100'); Query Plan: =========================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ------------------------------------------- |0 |DISTRIBUTED INSERT| |1 |20 | |1 | EXPRESSION | |1 |1 | =========================================== Outputs & filters: ------------------------------------- 0 - output([column_conv(NUMBER,PS:(38,0),NOT NULL,__values.C1)], [column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,__values.C2)]), filter(nil), columns([{T3: ({T3: (T3.C1, T3.C2)}, {IDX_T3_C2: (T3.C2, T3.C1)})}]), partitions(p0) 1 - output([__values.C1], [__values.C2]), filter(nil) values({1, '100'})