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' は3番目の演算子にプッシュダウンされています。 |
| 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の1つのパーティション内で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]) | +------------------------------------------------------------------+