插入空值时如何避免cassandra墓碑

插入空值时如何避免cassandra墓碑,cassandra,spark-cassandra-connector,Cassandra,Spark Cassandra Connector,我的问题是cassandra在插入空值时会创建墓碑 据我所知,cassandra不支持NULL,当插入NULL时,它只删除相应的列。一方面,这是非常节省空间的,但另一方面,它会创建墓碑,从而降低读取性能 这与NoSql哲学相去甚远,因为cassandra节省了空间,但降低了读取性能。在NoSql世界中,空间很便宜,但性能很重要。我相信这就是以非规范化形式保存表格背后的哲学 我希望cassandra使用与任何其他值相同的插入NULL的技术—使用时间戳并在压缩过程中保留最新条目—即使条目为NULL(

我的问题是cassandra在插入空值时会创建墓碑

据我所知,cassandra不支持NULL,当插入NULL时,它只删除相应的列。一方面,这是非常节省空间的,但另一方面,它会创建墓碑,从而降低读取性能

这与NoSql哲学相去甚远,因为cassandra节省了空间,但降低了读取性能。在NoSql世界中,空间很便宜,但性能很重要。我相信这就是以非规范化形式保存表格背后的哲学

我希望cassandra使用与任何其他值相同的插入NULL的技术—使用时间戳并在压缩过程中保留最新条目—即使条目为NULL(或者我们可以称之为“unset”)。 在cassandra配置中是否有任何调整,或者我如何能够在没有墓碑的情况下使用空值实现升级的方法

然而,我发现它只允许忽略空值

我的用例: 我有一连串的事件,每一个事件都由causeID标识。我收到许多具有相同causeId的事件,我只想存储相同causeId的最新事件(使用upsert)。事件的属性可以从NULL更改为特定值,也可以从特定值更改为NULL。不幸的是,后一种情况会产生墓碑并降低读取性能

更新


看来我没办法避开墓碑。你能给我一些关于如何最小化它们的技术建议吗(将gc_grace_seconds设置为非常低的值)。当节点宕机时间超过gc\u grace\u秒时,会有什么风险,该怎么办?

如果在插入中特别提到NULL,则无法避免出现墓碑。C*在插入或写入数据之前不进行查找,这使得写入速度非常快。为此,C*只需插入一个墓碑,以避免以后出现该值(使用最新的更新来比较时间戳)。如果要避免逻辑删除(建议这样做),必须准备不同的查询组合,在将每个查询添加到INSERT之前检查它们是否为NULL。如果要检查的字段很少,那么只需添加一些If-ELSE语句就很容易了。但是如果有很多,代码会更大,可读性也会更低。很快,您就不能插入NULL,这将影响以后的读取性能


您不能在Cassandra中插入NULL-它在那里有特殊的意义,并导致创建您观察到的墓碑。如果您想将NULL视为特殊值,为什么不在应用程序端解决这个问题呢?当您获得
NULL
状态时,只需插入任何无法在表中使用的特殊值,当您读回数据时,检查该特殊值并向请求者输出
null

在后一种情况下,null是什么意思-当从特定值更改为null时?将特定值更改为null的可能重复简化示例:创建表事件(id文本主键,事件文本);插入事件(“1”、“特定值”);插入事件('1',空);您不需要生成具有不同列组合的准备语句-只需对现有准备语句使用
unset
,如下所述:数据通过Spark app保存,我可以将Spark.cassandra.output.ignoreNulls=true,但这对我没有帮助,因为空值将被忽略,所以即使在应该删除旧列值时也会保留它们。如果要删除行或列(插入空值或使用delete语句),将生成墓碑。没有别的办法。C*未就地删除。如果要将null值用作null(unset或列没有当前值),只需将unset用作@AlexOtt或cassandra.output.ignoreNulls=true,如前所述。正如AlexOtt提到的,NULL在C*中有特殊含义,如果您想使用它删除之前的值,那么将生成墓碑。如果您想删除一个愿意忽略墓碑的数据,这在C*中是不可能的。谢谢您的建议,我也在考虑这个解决方案,但是在我看来,它似乎是一个解决方案,可以更直接地工作。这个解决方案有两个问题。1) 我正在存储一个复杂的嵌套数据结构,所以检查所有字段是一场噩梦。2) 存储在Cassandra中的数据不会被应用程序读取,数据将由数据科学家使用tableau、zeppelin、notebook等分析工具进行分析……您能展示您的表结构以及如何执行更新吗?不幸的是,我无法共享表结构,它是一个包含200行的DDL。该表有许多UDT,它有40个顶级属性,类型为:text、boolean、UDT、timestamp、int、list。数据从Kafka队列流式传输,使用Spark数据流进行处理,转换为DataFrame并保存到C*如果使用嵌套结构的冻结版本,则可以避免嵌套结构中的墓碑-如果通过Spark存储数据,则是完全写入数据,而不是更新表的部分。列表、映射和集合也是一样,我尝试使用冻结结构,当我将它们设置为null时,它们也会创建墓碑,我不知道如何更新空UDT(我可以对空数组执行此操作)。有趣的是,当我将冻结UDT设置为null时,cqlsh的跟踪信息显示它没有读取任何墓碑。但是sstabledump显示删除的标记。。。