ワイドテーブルに列単位で書き込む際、INSERT や UPDATE のたびに全列を指定する必要がある場合、コストが高くなります。列の部分更新機能は、この制約を解消します。変更したい列のみを指定すれば、操作タイプに基づいて残りは MaxCompute が自動的に処理します。
仕組み
指定されなかった列の動作は、操作によって異なります。
操作 | 指定されなかった列 |
INSERT INTO / INSERT OVERWRITE | NULL に設定 |
UPDATE | 変更しない |
MERGE INTO (WHEN MATCHED UPDATE SET) | 変更しない |
MERGE INTO (WHEN NOT MATCHED INSERT) | NULL に設定 |
この違いを理解することが最も重要です。INSERT では指定されなかった列は NULL で補完されますが、UPDATE と WHEN MATCHED では指定されなかった列は変更されません。
ユースケース
最も一般的なユースケースは、スタースキーマからワイドテーブルを構築することです。複数のソーステーブルが同じプライマリキーを共有している場合、各ソーステーブルの列をワイドテーブルに独立して並列に書き込みます。読み取り時には、MaxCompute がプライマリキーに基づいて行をマージし、完全なレコードを返します。すべての列を 1 回の操作で書き込む場合と比べて、この方法は書き込みと読み取りのパフォーマンスを向上させ、ストレージコストを削減します。
前提条件
開始する前に、以下の要件を満たしていることを確認してください。
列の部分更新が有効化された Delta テーブル (「Delta テーブルの作成」を参照)
MaxCompute の DML ステートメント (INSERT INTO、UPDATE、DELETE、MERGE INTO) に関する知識
Delta テーブルの作成
列の部分更新を有効にするには、テーブル作成時に 2 つのテーブルプロパティを設定します。
CREATE TABLE delta_target
(
key BIGINT NOT NULL PRIMARY KEY,
b STRING,
c BIGINT
)
TBLPROPERTIES (
"acid.partial.fields.update.enable" = "true",
"transactional" = "true"
);acid.partial.fields.update.enable と transactional は、両方とも "true" に設定する必要があります。パーティションテーブルと非パーティションテーブルのどちらもサポートされています。
特定列へのデータ挿入
INSERT INTO を使用して、一部の列に値を書き込みます。列リストに含まれていない列は NULL に設定されます。すでに存在するプライマリキーを持つ行を挿入すると、MaxCompute は指定した列のみを更新し、その他の列は変更しません。これは、実質的に挿入による部分更新となります。
例 1:新しい行を挿入し、列 c を省略
列 c は指定されていないため、NULL に設定されます。
INSERT INTO TABLE delta_target(key, b) VALUES(1, '1');
SELECT * FROM delta_target;結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 1 | 1 | NULL |
+------------+------------+------------+例 2:重複するプライマリキーを持つ行を挿入して特定の列を更新
key=1 の行はすでに存在します。同じプライマリキーで挿入すると、指定した列 (c) が更新され、指定しなかった列 (b) は変更されません。
INSERT INTO TABLE delta_target(key, c) VALUES(1, 1);
SELECT * FROM delta_target;結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 1 | 1 | 1 |
+------------+------------+------------+例 3:c を変更せずに別の列を更新
列 c は指定されていないため、現在の値 1 が保持されます。
INSERT INTO TABLE delta_target(key, b) VALUES(1, '11');
SELECT * FROM delta_target;結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 1 | 11 | 1 |
+------------+------------+------------+例 4:新しいプライマリキーを持つ行を挿入
プライマリキーがまだ存在しない場合、新しい行が挿入されます。
INSERT INTO TABLE delta_target VALUES(2, '2', 2);
SELECT * FROM delta_target;結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 2 | 2 | 2 |
| 1 | 11 | 1 |
+------------+------------+------------+詳細については、「テーブルまたは静的パーティションへのデータの挿入または上書き(INSERT INTO と INSERT OVERWRITE)」をご参照ください。
既存行の特定列の更新
UPDATE を使用して、一致する行の特定の列を変更します。SET 句に含まれていない列は変更されません。
例 1:key=1 の列 b を更新し、c は変更しない
UPDATE delta_target SET b='111' WHERE key=1;
SELECT * FROM delta_target;結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 2 | 2 | 2 |
| 1 | 111 | 1 |
+------------+------------+------------+例 2:key=2 の列 b を更新し、c は変更しない
UPDATE delta_target SET b='222' WHERE key=2;
SELECT * FROM delta_target;結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 2 | 222 | 2 |
| 1 | 111 | 1 |
+------------+------------+------------+詳細については、「UPDATE と DELETE」をご参照ください。
ソースデータの特定列へのマージ
MERGE INTO を使用して、特定の列のみを対象としてアップサートを実行します。WHEN MATCHED 句では、指定された列のみが更新され、それ以外の列は変更されません。WHEN NOT MATCHED 句では、指定のない列は NULL に設定されます。
次の例ではソーステーブルを作成し、それを delta_target にマージします。このマージでは、一致する行の列 b を更新し、新しい行については (key, b) を挿入します。いずれの場合も、列 c には書き込みを行いません。
-- 6 行を含むソーステーブルを作成
CREATE TABLE acid2_dml_pu_source AS
SELECT key, b, c
FROM VALUES
(1, '10', 10),
(2, '20', 20),
(3, '30', 30),
(4, '40', 40),
(5, '50', 50),
(6, '60', 60) t (key, b, c);
-- マージ:一致する行は b を更新し、新しい行は (key, b) を挿入
MERGE INTO delta_target AS t
USING acid2_dml_pu_source AS s ON s.key = t.key
WHEN MATCHED THEN
UPDATE SET t.b = s.b
WHEN NOT MATCHED THEN
INSERT (key, b) VALUES(s.key, s.b);結果:
+------------+------------+------------+
| key | b | c |
+------------+------------+------------+
| 3 | 30 | NULL |
| 4 | 40 | NULL |
| 5 | 50 | NULL |
| 6 | 60 | NULL |
| 2 | 20 | 2 |
| 1 | 10 | 1 |
+------------+------------+------------+行 3~6 は新規挿入です。列 c は指定されていないため NULL になります。行 1 と 2 は一致したため、列 b は更新され、c は以前の値が保持されます。
詳細については、「MERGE INTO」をご参照ください。