对于Cassandra,如果所选行不存在,UPDATE
s是否会成为隐含的INSERT
?也就是说,如果我说
UPDATE users SET name = "Raedwald" WHERE id = 545127
而id
是users
表的PRIMARY KEY
,并且该表没有键为545127的行,这是否等同于
INSERT INTO users (id, name) VALUES (545127, "Raedwald")
我知道事实恰恰相反:已经存在的id
的INSERT
变成具有该id
的行的UPDATE
。旧的Cassandra文档提到插入实际上是“upsert”。
我对CQL3,Cassandra版本1.2+的案例感兴趣。
4条答案
按热度按时间ncgqoxb01#
是的,对于Cassandra,
UPDATE
与INSERT
是同义词,正如CQL文档中所解释的那样,它对UPDATE
的描述如下:请注意,与SQL不同,
UPDATE
不会检查行是否存在:如果之前不存在行,则创建该行,否则更新该行。此外,没有办法知道发生了创建或更新中的哪一个。实际上,INSERT
和UPDATE
的语义是相同的。为了使语义不同,Cassandra需要执行读取以了解行是否已经存在。Cassandra是写优化的,因此您可以始终假设它在任何写操作中都不会在写之前执行读操作。唯一的例外是计数器(除非
replicate_on_write = false
),在这种情况下,增量复制涉及读取。x0fgdtte2#
不幸的是,公认的答案并不是100%准确。
insert
s与update
s不同:Scylla也是一样。
在Scylla和Cassandra中,行是 * 细胞 * 的序列。每一列都有一个对应的单元格(如果是非冻结集合或UDT,则是一组单元格)。但是还有一个额外的、不可见的单元格--* 行标记 *(至少在Scylla中是这样;我怀疑Cassandra有类似的东西)。
行标记会对所有其他单元格都已死亡的行产生影响:当且仅当至少有一个活细胞时,查询中才会显示一行。因此,如果行标记是活动的,则该行将显示,即使所有其他列先前使用例如
update
s.insert
s创建一个 * 活动行标记 *,而update
s不接触行标记,所以很明显它们是不同的。上面的例子说明了这一点。有人可能会说行标记是Cassandra/Scylla的“内部”,但正如您所看到的,它们的效果是可见的。行标记会影响你的生活,不管你喜欢与否,所以记住它们可能是有用的。遗憾的是,没有文档提到行标记(好吧,我发现了这个:https://docs.scylladb.com/architecture/sstable/sstable2/sstable-data-file/#cql-row-marker,但它是在解释SSTable内部的上下文中,这可能更多地是致力于Scylla开发人员而不是用户)。
奖励:一个 * 单元格删除 *:
与
null
更新相同:实际上,单元格删除也不会触及行标记。它只将指定的单元格设置为
null
。这与 row delete 不同:
因为row deletes插入一个 row tombstone,这会杀死行中的所有单元格(包括行标记)。可以说行删除与插入相反。更新和单元格删除介于两者之间。
8dtrkrch3#
然而,我们可以做的是:
这将确保您的更新是真正的更新,而不是更新。
6ju8rftf4#
不,它们不相等,正如@kbr已经解释的那样。您可以在这篇Scylla文档文章中阅读更多关于
UPDATE
和INSERT
语句之间的区别-这是开发人员自己最深入的解释。简而言之,对于表:
声明:
相当于: