即使未使用 where 子句选择,Cassandra 中的逻辑删除也会减慢查询速度

Do tombstones in Cassandra slow down queries even when not selected with where clause

如果我有一个分区,一个集群中有 100'000 个已删除行,然后是同一分区中没有删除行的第二个集群,执行 SELECT * FROM example_table WHERE partition=that_partition AND cluster=the_second_cluster 的性能是否会受到墓碑的影响出现在 the_first_cluster?

我希望如果使用 where 子句检索行集是常量,那么 Cassandra 将跳过所有墓碑到第二个集群,但我不明白 where 子句如何找到正确的行,所以我不知道是否是这种情况,我也没有设法在网上找到任何可以启发我的东西。

// Example table
CREATE TABLE example_table (
  partition TEXT,
  cluster TEXT,
  value BLOB,

  PRIMARY KEY (partition, cluster);

// Example layout of rows in a table
partition      |cluster            |value
that_partition |the_first_cluster  |some_value1 // Deleted, a tombstone
that_partition |the_first_cluster  |some_value2 // Deleted, a tombstone
... 99'997 more similar tombstone rows
that_partition |the_first_cluster  |some_value  // Deleted, a tombstone
that_partition |the_second_cluster |some_valueA // Not a tombstone
that_partition |the_second_cluster |some_valueB // Not a tombstone
... no tombstones in the_second_cluster

分区上的大量墓碑如果包含在结果中,将显着影响性能。一篇很好的文章 https://www.datastax.com/dev/blog/cassandra-anti-patterns-queues-and-queue-like-datasets 谈到了它。根据查询,它可能最终会读取所有 100,000 个墓碑,如果在不同的 sstable 上也可能读取原始数据以满足查询。这会在堆上生成 lot 垃圾,并且会影响 JVM GC 以及单个查询的大量 CPU 和 IO。

但是,如果墓碑是点删除而不是范围墓碑,并且您的查询直接转到未删除的键的分区+聚类,您就可以了。不过这是一条很好的路线,我建议不要尝试这样做(如果有人试图将其作为 ops/test 任务从应用程序中读取怎么办?这可能会导致长时间的 GC 并对集群产生负面影响)。保留在分区索引中的范围墓碑被反序列化为读取跳转到的位置以进入行的列索引大小的一部分,因此即使不直接读取它们,它仍然会显着影响分配率,具体取决于您的墓碑是如何插入的。

cassandra.yaml 中设置了墓碑 warn/failure 阈值,因此它会让您知道您的查询是否命中它们,但在您遇到故障点和查询之前很难判断自从刚刚在日志中报告后就死了。

我建议您对分区进行时间限制,以限制每个分区中的墓碑数量。