UPDATE是否成为隐含的​​INSERT

时间:2013-06-27 16:33:36

标签: cassandra cql

对于Cassandra,如果所选行不存在,UPDATE会成为隐含的​​INSERT吗?也就是说,如果我说

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

idPRIMARY KEY表的users,表中没有行,键为545127,这相当于

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

我知道情况正好相反:已存在的INSERT的{​​{1}}成为id行的UPDATE。较早的Cassandra文档谈到了插入实际上是“upserts”的原因。

我对CQL3,Cassandra版本1.2 +的情况感兴趣。

3 个答案:

答案 0 :(得分:37)

是的,对于Cassandra UPDATEINSERT的同义词,正如the CQL documentation中所解释的那样,UPDATE说明了以下内容:

  

请注意,与SQL不同,UPDATE不检查行的先前存在:如果之前不存在,则创建行,否则更新。此外,没有必要知道发生了哪些创建或更新。事实上,INSERTUPDATE的语义是相同的。

对于不同的语义,Cassandra需要读取以了解该行是否已存在。 Cassandra是写入优化的,因此您可以始终假设它在写入任何写入操作之前不会执行读取操作。唯一的例外是计数器(除非replicate_on_write = false),在这种情况下,增量复制涉及读取。

答案 1 :(得分:20)

很遗憾,接受的答案不是100%准确。 insert s与update s不同:

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做同样的事情。

在Scylla和Cassandra中,行是单元格的序列。每列都有一个对应的单元格(如果是非冻结集合或UDT,则为一组单元格)。但是还有另外一个不可见的单元格-行标记(至少在Scylla中;我怀疑Cassandra也有类似的东西)。

行标记对于所有其他单元格均已失效的行有所不同:当且仅当至少有一个活动单元格时,查询中才会显示一行。因此,如果行标记处于活动状态,即使先前已使用(例如)将所有其他列设置为null,也将显示该行。 update

insert创建了实时行标记,而update没有创建行标记,因此显然它们是不同的。上面的示例说明了这一点。 有人可能会说行标记是Cassandra / Scylla的“内部”,但是如您所见,它们的效果是可见的。行标记会影响您的生活,无论您是否喜欢它,因此记住它们可能会很有用。

可悲的是,没有任何文档提到行标记(嗯,我发现了这一点:https://docs.scylladb.com/architecture/sstable/sstable2/sstable-data-file/#cql-row-marker,但这是在解释SSTable内部原理的背景下进行的,它可能是Scylla开发人员而不是用户所专用的。)

奖金:单元格删除

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

这与行删除不同:

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

因为行删除插入行墓碑,该行将杀死该行中的所有单元格(包括行标记)。您可以说行删除与插入相反。更新和单元格删除介于两者之间。

答案 2 :(得分:13)

然而,人们可以做的是:

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

这将确保您的更新是真正的更新,而不是upsert。