UPDATE演算子は、指定された条件を満たすデータ行をデータテーブルで更新するために使用されます。
OceanBaseデータベースがサポートするUPDATE演算子には、UPDATEとDISTRIBUTED UPDATEが含まれます。
UPDATE
UPDATE演算子は、データテーブルの単一パーティション内のデータを更新するために使用されます。
以下の例のように、Q1クエリはテーブルt1内でc2 = '100'を満たすすべての行を更新し、c2列の値を200に設定します。
--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 UPDATE t1 SET c2 = '200' WHERE c2 = '100';
Query Plan:
======================================
|ID|OPERATOR |NAME|EST. ROWS|COST |
-----------------------------------------------
|0 |EXCHANGE IN REMOTE | |990 |109687|
|1 | EXCHANGE OUT REMOTE| |990 |109687|
|2 | UPDATE | |990 |109687|
|3 | TABLE SCAN |T1 |990 |108697|
===============================================
Outputs & filters:
-------------------------------------
0 - output(nil), filter(nil)
1 - output(nil), filter(nil)
2 - output(nil), filter(nil), table_columns([{T1: ({T1: (T1.C1, T1.C2)})}]),
update([T1.C2=?])
3 - output([T1.C1], [T1.C2], [?]), filter([T1.C2 = '100')),
access([T1.C2], [T1.C1]), partitions(p0)
上記の例では、実行計画表示のoutputs & filters詳細列にUPDATE演算子の出力情報が次のように詳細に示されています:
| 情報名 | 意味 |
|---|---|
| output | この演算子が出力する式。 |
| filter | この演算子のフィルタ条件。例ではUPDATE演算子にfilterがないため、nilとなります。更新ステートメントについては、WHERE句の述語がベーステーブルにプッシュダウンされます。例えば、Q1クエリ内のc2 = '100'は、1番目の演算子にプッシュダウンされました。 |
| table_columns | 更新操作に関連するデータテーブルの列。 |
| update | 更新操作におけるすべての代入式。 |
その他のUPDATE演算子の例は次のとおりです:
Q2クエリは、テーブル
t1内のすべてのデータ行を更新し、c2列の値を200に設定します。Q2:
obclient> EXPLAIN UPDATE t1 SET c2 = '200';実行結果は次のとおりです:
Query Plan: ====================================== |ID|OPERATOR |NAME|EST. ROWS|COST | ----------------------------------------------- |0 |EXCHANGE IN REMOTE | |100000 |161860| |1 | EXCHANGE OUT REMOTE| |100000 |161860| |2 | UPDATE | |100000 |161860| |3 | TABLE SCAN |T1 |100000 |61860 | =============================================== Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) 1 - output(nil), filter(nil) 2 - output(nil), filter(nil), table_columns([{T1: ({T1: (T1.C1, T1.C2)})}]), update([T1.C2=?]) 3 - output([T1.C1], [T1.C2], [?]), filter(nil), access([T1.C2], [T1.C1]), partitions(p0)Q3クエリは、パーティションテーブル
t2内でc1='100'を満たすデータ行を更新し、c2列の値を150に設定します。Q3:
obclient> EXPLAIN UPDATE t2 SET t2.c2 = '150' WHERE t2.c1 = '100';実行結果は次のとおりです:
Query Plan: =================================== |ID|OPERATOR |NAME|EST. ROWS|COST| ----------------------------------- |0 |UPDATE | |1 |53 | |1 | TABLE GET|T2 |1 |52 | =================================== Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil), table_columns([{T2: ({T2: (T2.C1, T2.C2)})}]), update([T2.C2=?]) 1 - output([T2.C1], [T2.C2], [?]), filter(nil), access([T2.C1], [T2.C2]), partitions(p5)Q4クエリは、パーティションテーブル
t2内でc2 ='100'を満たすデータ行を更新し、c2列の値をrpad(t2.c2, 10, '9')に設定します。実行計画からわかるように、UPDATE演算子はEXCHANGE演算子の下に配置されているため、2番目と3番目の演算子はパーティション単位でスケジュールされるタスクとして実行されます。実行時に4番目の演算子はt2のパーティション内でc2 = '100'を満たすデータをスキャンし、3番目のUPDATE演算子は対応するパーティション内でスキャンされたデータのみを更新します。Q4:
obclient> EXPLAIN UPDATE t2 SET t2.c2 = RPAD(t2.c2, 10, '9') WHERE t2.c2 = '100';実行結果は次のとおりです:
Query Plan: =============================================== |ID|OPERATOR |NAME |EST. ROWS|COST | ------------------------------------------------------- |0 |PX COORDINATOR | |9900 |1096793| |1 | EXCHANGE OUT DISTR |:EX10000|9900 |1096793| |2 | PX PARTITION ITERATOR| |9900 |1096793| |3 | UPDATE | |9900 |1096793| |4 | TABLE SCAN |T2 |9900 |1086893| ======================================================= Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) 1 - output(nil), filter(nil), dop=1 2 - output(nil), filter(nil) 3 - output(nil), filter(nil), table_columns([{T2: ({T2: (T2.C1, T2.C2)})}]), update([T2.C2=column_conv(VARCHAR,utf8mb4_bin,length:10,NULL,RPAD(T2.C2, 10, ?))]) 4 - output([T2.C1], [T2.C2], [column_conv(VARCHAR,utf8mb4_bin,length:10,NULL,RPAD(T2.C2, 10, ?))]), filter([T2.C2 = '100']), access([T2.C1], [T2.C2]), partitions(p[0-9])
DISTRIBUTED UPDATE
DISTRIBUTED UPDATE 演算子は、データテーブルの複数のパーティションにあるデータを更新することを示します。以下の例のように、Q5クエリは t3 テーブル内で c2 < '100' を満たすすべてのデータ行を更新し、c2 列の値を200に設定します。t3 は非パーティションテーブルですが、t3 テーブルにはグローバルインデックス idx_t3_c2 が存在するため、各データ行は複数のパーティションに存在します。
Q5:
obclient> EXPLAIN UPDATE t3 SET c2 = '200' WHERE c2 < '100';
+--------------------------------------------------------------------------------------------------------+
| Query Plan |
+--------------------------------------------------------------------------------------------------------+
| ======================================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------------------------------- |
| |0 |DISTRIBUTED UPDATE | |1 |61 | |
| |1 |└─DISTRIBUTED TABLE RANGE SCAN|T3(IDX_T3_C2)|1 |6 | |
| ======================================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output(nil), filter(nil) |
| table_columns([{T3: ({T3: (T3.C1, T3.C2)}, {IDX_T3_C2: (T3.C2, T3.C1)})}]), |
| update([T3.C2=column_conv(VARCHAR2,utf8mb4_bin,length:10,NULL,cast('200', VARCHAR2(1048576 )))]) |
| 1 - output([T3.C1], [T3.C2]), filter(nil), rowset=256 |
| access([T3.C1], [T3.C2]), partitions(p[0-2]) |
| is_index_back=false, is_global_index=true, |
| range_key([T3.C2], [T3.C1]), range(MIN,MIN ; 100,MIN), |
| range_cond([T3.C2 < cast('100', VARCHAR2(1048576 ))]) |
+--------------------------------------------------------------------------------------------------------+
その他の DISTRIBUTED UPDATE の例は次のとおりです:
- Q6クエリは、パーティションテーブル
t2内でc1 = 100を満たすデータ行を更新し、c1列の値を101に設定します。更新される列が主キー列であるため、更新後のデータ行と更新前のデータ行が異なるパーティションに配置される可能性があります。そのため、更新にはDISTRIBUTED UPDATE演算子を使用する必要があります。
Q6:
obclient> EXPLAIN UPDATE t2 SET t2.c1 = 101 WHERE t2.c1 = 100;
+------------------------------------------------------------------+
| Query Plan |
+------------------------------------------------------------------+
| ================================================== |
| |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| |
| -------------------------------------------------- |
| |0 |DISTRIBUTED UPDATE| |1 |34 | |
| |1 |└─TABLE GET |T2 |1 |3 | |
| ================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output(nil), filter(nil) |
| table_columns([{T2: ({T2: (T2.C1, T2.C2)})}]), |
| update([T2.C1=column_conv(NUMBER,PS:(-1,0),NOT NULL,101)]) |
| 1 - output([T2.C1], [T2.C2]), filter(nil), rowset=256 |
| access([T2.C1], [T2.C2]), partitions(p5) |
| is_index_back=false, is_global_index=false, |
| range_key([T2.C1]), range[100 ; 100], |
| range_cond([T2.C1 = 100]) |
+------------------------------------------------------------------+