INSERT演算子は、指定されたデータをデータテーブルに挿入するために使用されます。データソースには、直接指定された値とサブクエリの結果が含まれます。
OceanBaseデータベースがサポートするINSERT演算子には、通常のINSERTとDISTRIBUTED INSERTの2種類があります。
通常のINSERT
通常のINSERTは、データテーブルの単一パーティションにデータを挿入するために使用されます。
以下の例のように、Q1クエリは値(1, '100')をパーティション化されていないテーブルt1に挿入します。ここで、演算子EXPRESSION1は定数式の値を生成するために使用されます。
--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 | 挿入操作に関連するデータテーブルのパーティション(パーティションテーブルでない場合は、単一のパーティションを持つパーティションテーブルとみなすことができます)。 |
その他の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'})