UPDATE 文を使用すると、指定された条件に一致する行の列値を変更できます。
構文
UPDATE <table> [ * ] [ [ AS ] <alias> ]
SET { <column> = { <expression> } |
( <column> [, ...] ) = ( { <expression> } [, ...] ) } [, ...]
[ FROM <from_list> ]
[ WHERE <condition> ]パラメーター
| パラメーター | 説明 |
|---|---|
table | 更新対象のテーブル名です。 |
alias | テーブルの別名です。 |
column | 更新対象の列名です。 |
expression | 列の新しい値を生成する式です。 |
from_list | 他のテーブルからデータを取得して更新する場合に使用される、ソーステーブル内の列です。 |
condition | 更新対象となる行が満たす必要がある条件です。この条件に一致しない行は変更されません。 |
PostgreSQL の UPDATE 文の完全な仕様については、「UPDATE」をご参照ください。
仕組み
Hologres の各テーブルには、データファイル、主キーインデックスファイル、およびタグファイルの 3 つの関連ファイルがあります。タグファイルは、DELETE、UPDATE、INSERT ON CONFLICT などのステートメントによるデータの削除または更新を行うシナリオで主に使用されます。主キーインデックスファイルの詳細については、「PK」をご参照ください。
UPDATE を実行すると、Hologres はまず新しいデータをメモリテーブル(Mem Table)に書き込み、その後非同期でディスクにフラッシュします。
行指向テーブル:新規データは新しいファイルにフラッシュされます。古いデータはバックグラウンドでのコンパクション時にマージされて削除されます。
列指向テーブル:Hologres は、置き換え対象のデータのファイル ID と行 ID を記録するタグテーブルをメモリ上に構築します。新規データは新しいファイルにフラッシュされ、タグテーブルはタグファイルにフラッシュされます。コンパクション実行時に、Hologres は古いデータをクリアし、新規データをマージします。
コンパクションは非同期で実行されるため、UPDATE 実行中はストレージ使用量が増加し、コンパクション完了後に通常の状態に戻ります。
行指向テーブルの更新効率は、列指向テーブルよりも高くなります。
プライマリキーを持つテーブル
テーブルにプライマリキーが定義されている場合、Hologres は主キーインデックスファイルを用いて行識別子(RID)を検索し、対象のデータファイルを直接特定します。これにより、関係のないファイルをスキップして、該当する行のみを更新できます。
プライマリキーが定義されていない場合、Hologres は該当する行を検索するためにテーブル全体をスキャンする必要があり、パフォーマンスに影響を与えます。詳細については、「PK」をご参照ください。
部分更新
部分更新では、行内の一部の列のみを変更し、他の列はそのまま保持します。これは Hologres 固有の機能であり、さまざまなビジネス要件に対応できます。すべての 3 種類のストレージフォーマットで部分更新がサポートされていますが、読み取り→書き込み(read-before-write)の処理方法は異なります。
| ストレージフォーマット | 部分更新の動作 |
|---|---|
| 行指向 | ログ構造型マージ(LSM)構造を用いた追記専用(Append Only)モードでデータが書き込まれます。読み取り→書き込みは不要です。 |
| 列指向 | 新規データの書き込み前に空の列を読み取る必要があります。これにより、リソース消費量が増加します。 |
| 行・列ハイブリッド | 空の列は行指向部分から読み取られるため、列指向テーブルと比較してリソース消費量が低減されます。 |
固定プランを有効化した場合、部分更新のパフォーマンスは以下の順に高速です(高速 → 低速):
行指向 > 行・列ハイブリッド > 列指向
固定プランを無効化した場合、部分更新は 2 つのテーブル間の結合(テーブル結合)として処理されます。この場合、パフォーマンスの順位は異なります:
列指向 > 行・列ハイブリッド > 行指向
固定プランを有効化したリアルタイム更新ワークロードでは、行指向テーブルが最も優れたパフォーマンスを発揮します。固定プランの有効化方法については、「UPDATE 文」をご参照ください。
制限事項
分散キーは更新できません。 分散キーの値を変更するには、該当行を削除した後、新しい値で再挿入してください。
パーティションテーブルを更新すると、親テーブルではなく子テーブルが更新されます。 更新対象の行を含む特定の子テーブルに対して UPDATE を実行してください。
パフォーマンス向上のため、固定プランを有効化することを推奨します。 固定プランを無効化すると、部分更新はテーブル結合として処理されるため、パフォーマンス特性およびストレージフォーマットごとのパフォーマンス順位が変化します。「UPDATE 文」をご参照ください。
例
以下の例では、サンプルテーブルを使用します。
CREATE TABLE update_test (
a text primary key,
b int not null,
c text not null,
d text
);
INSERT INTO update_test VALUES ('b1', 10, '', '');算術式を用いた列の更新
UPDATE update_test SET b = b + 10 WHERE a = 'b1';他の列の条件を用いた複数列の更新
UPDATE update_test SET c = 'new_' || a, d = null WHERE b = 20;WHERE 句を指定せずに複数列を更新(全行が更新対象)
UPDATE update_test SET (b, c, d) = (1, 'test_c', 'test_d');他のテーブルからのデータを用いた列の更新
CREATE TABLE tmp (a int);
INSERT INTO tmp VALUES (2);
UPDATE update_test SET b = tmp.a FROM tmp;部分更新:1 つの列のみを更新し、他の列は変更しない
CREATE TABLE update_test2 (
col1 text NOT NULL PRIMARY KEY,
col2 text,
col3 text
);
INSERT INTO update_test2 VALUES ('a1', 'a2', 'a3'), ('a11', 'a22', 'a33');
-- col2 のみを更新;col3 は変更されない
UPDATE update_test2 SET col2 = 'tom' WHERE col1 = 'a1';結果:
col1 | col2 | col3
------+------+------
a1 | tom | a3
a11 | a22 | a33
(2 rows)同様の部分更新は、INSERT ON CONFLICT を用いて以下のように記述することもできます。
INSERT INTO update_test2 (col1, col2) VALUES ('a1', 'tom')
ON CONFLICT (col1) DO UPDATE
SET col2 = EXCLUDED.col2;よくある質問
UPDATE 実行中にストレージ使用量が急増し、その後減少するのはなぜですか?

UPDATE 実行中、Hologres は古いデータを削除対象としてタグ付けし、新しいデータを即座に小さなファイルにフラッシュします。タグ付けされた古いデータと新しいファイルは、バックグラウンドのコンパクションが実行されるまで共存します。コンパクションでは、新しいデータがマージされ、古いデータがクリアされ、小さなファイルが統合されます。この時点でストレージ使用量は通常の状態に戻ります。詳細については、「仕組み」をご参照ください。