UPDATE
对 Cassandra 执行 CQL和INSERT
执行 CQL之间有什么区别?
看起来以前没有区别,但现在文档说不INSERT
支持计数器,而支持UPDATE
。
是否有“首选”方法可以使用?或者在某些情况下应该使用一个而不是另一个?
非常感谢!
有细微的差别。如果将所有非关键字段设置为空,则通过 INSERT 插入的记录仍然存在。如果您将所有非关键字段设置为空,则通过 UPDATE 插入的记录将消失。
尝试这个:
CREATE TABLE T (
pk int,
f1 int,
PRIMARY KEY (pk)
);
INSERT INTO T (pk, f1) VALUES (1, 1);
UPDATE T SET f1=2 where pk=2;
SELECT * FROM T;
回报:
pk | f1
----+----
1 | 1
2 | 2
现在,将每行设置 f1 更新为 null。
UPDATE T SET f1 = null WHERE pk = 1;
UPDATE T SET f1 = null WHERE pk = 2;
SELECT * FROM T;
请注意,保留第 1 行,而删除第 2 行。
pk | f1
----+------
1 | null
如果您使用 Cassandra-cli 查看这些内容,您会发现添加行的方式有所不同。
我很想知道这是设计使然还是错误,并查看记录此行为。
Cassandra 中的计数器列不能设置为任意值:它们只能按任意值递增或递减。
出于这个原因,INSERT
不支持计数器列,因为您不能将值“插入”到计数器列中。您只能UPDATE
将它们(增加或减少)某个值。以下是更新 Counter 列的方法。
UPDATE ... SET name1 = name1 + <value>
您问:
是否有“首选”方法可以使用?或者在某些情况下应该使用一个而不是另一个?
是的。如果要将值插入数据库,则可以使用INSERT
. 如果该列不存在,它将为您创建。否则,INSERT
的效果类似于UPDATE
。INSERT
当您没有预先设计的架构(动态列族,即随时插入任何内容)时,这很有用。如果您事先设计了模式(静态列族,类似于 RDMS)并且知道每一列,那么您可以使用UPDATE
.
另一个微妙的区别(我开始相信 cql 是一个糟糕的 cassandra 接口,由于使用了类似的 SQL 语法但语义略有不同,因此充满了微妙之处和警告)是在现有数据上设置 TTL。UPDATE
即使新的实际值等于旧值,您也无法更新键的 TTL 。解决方案是改为插入新行,新的 TTL 已经设置
关于 billbaird 强调的细微差别(我无法直接评论该帖子),如果所有非关键字段都为空,则更新操作创建的行将被删除:
这是预期的行为,而不是基于https://issues.apache.org/jira/browse/CASSANDRA-11805上的错误报告的错误(已关闭为“不是问题”)
我第一次使用 Spring Data 时遇到了这个问题。我正在使用save(T entity)
存储库的方法,但没有创建任何行。事实证明 Spring Data 使用的是,UPDATE
因为它确定该对象不是“新的”(不确定“isNew”的测试在这里是否有意义),而我碰巧正在使用仅设置了关键字段的实体进行测试。
对于这个 Spring Data 案例,Cassandra 特定的存储库接口确实提供了一种insert
方法,该方法似乎始终使用INSERT
if 该行为来代替(尽管 Spring 的文档也没有充分记录这些细节)。