web-dev-qa-db-ja.com

UPDATEは暗黙のINSERTになりますか

Cassandraの場合、選択した行が存在しない場合、UPDATEsは暗黙のINSERTになりますか?つまり、私が言うなら

 UPDATE users SET name = "Raedwald" WHERE id = 545127

idPRIMARY KEY of the users table、a​​nd the row has no row with a key 545127、that will it equal to

 INSERT INTO users (id, name) VALUES (545127, "Raedwald")

私はその逆が真であることを知っています。すでに存在するINSERTidは、そのUPDATEを持つ行のidになります。古いCassandraドキュメンテーションは、その理由で実際に挿入が「upsert」である挿入について話しました。

CQL3のケースに興味があります、Cassandraバージョン1.2+。

38
Raedwald

はい、Cassandra UPDATEINSERTと同義です。これは CQLドキュメント で説明されています。ここでUPDATE

SQLとは異なり、UPDATEは行の以前の存在を確認しないことに注意してください。以前に行が存在しない場合は行が作成され、それ以外の場合は更新されます。さらに、作成と更新のどちらが起こったかを知る手段はありません。実際、INSERTUPDATEの意味は同じです。

セマンティクスが異なる場合、Cassandraは、行がすでに存在するかどうかを知るために読み取りを行う必要があります。Cassandraは書き込み最適化されているため、常に書き込み操作では、書き込み前に読み取りを行いません。唯一の例外はカウンターです(unlessreplicate_on_write = false)。この場合、増分のレプリケーションには読み取りが含まれます。

40
Richard

残念ながら、受け入れられた答えは100%正確ではありません。 insertsはupdatesとは異なります:

cqlsh> create table ks.t (pk int, ck int, v int, primary key (pk, ck));
cqlsh> update ks.t set v = null where pk = 0 and ck = 0;
cqlsh> select * from ks.t where pk = 0 and ck = 0;

 pk | ck | v
----+----+---

(0 rows)
cqlsh> insert into ks.t (pk,ck,v) values (0,0,null);
cqlsh> select * from ks.t where pk = 0 and ck = 0;

 pk | ck | v
----+----+------
  0 |  0 | null

(1 rows)

スキュラも同じことをします。

ScyllaとCassandra行はcellsのシーケンスです。各列は対応するセル(または非凍結コレクションまたはUDTの場合。ただし、1つの追加の非表示のセルがあります-行マーカー(少なくともScyllaで、私は= Cassandraは同様のものを持っています)。

行マーカーは、他のすべてのセルが無効になっている行に違いをもたらします。行は、少なくとも1つの生きているセルがある場合にのみ、クエリに表示されます。したがって、行マーカーが有効な場合、他のすべての列が以前にnullに設定されていても、その行は表示されます。 updates。

insertsはライブ行マーカーを作成しますが、updatesは行マーカーに触れないため、明らかに異なります。上記の例はそれを示しています。行マーカーはCassandra/Scyllaの「内部」にあると主張することもできますが、ご覧のとおり、その効果は目に見えます。行マーカーは、あなたが好きかどうかに関係なくあなたの人生に影響を与えるので、それらについて覚えておくと役に立ちます。

ドキュメントが行マーカーについて言及していないのは残念です(まあ、私はこれを見つけました: https://docs.scylladb.com/architecture/sstable/sstable2/sstable-data-file/#cql-row-marker しかし、それはSSTableの内部を説明するコンテキストにあります。SSTableの内部は、おそらくユーザーよりもScylla開発者に捧げられています)。

ボーナス:aセル削除

delete v from ks.t where pk = 0 and ck = 0

nullアップデートと同じです:

update ks.t set v = null where pk = 0 and ck = 0

実際、セルの削除も行マーカーには影響しません。指定されたセルをnullに設定するだけです。

これはrow deleteとは異なります。

delete from ks.t where pk = 0 and ck = 0

行を削除すると、行の墓石が挿入され、行内のすべてのセル(行マーカーを含む)が削除されるためです。行の削除は挿入の反対であると言えます。更新とセルの削除は、その中間にあります。

17
kbr

ただし、これができることは次のとおりです。

UPDATE table_name SET field = false WHERE key = 55 IF EXISTS;

これにより、更新が真の更新であり、アップサートではないことが保証されます。

15