SELECT LIMIT 1 的墓碑警告

Tombstone warning with SELECT LIMIT 1

CREATE TABLE test (
    ck INT, 
    pk INT, 
    PRIMARY KEY (ck, pk)
);

for (int i = 1; i < 10000; i++) {
    sessionRW.execute(QueryBuilder.insertInto("test").value("ck", 1).value("pk", i));
}

root@cqlsh:ks> select * from test limit 5;

 ck | pk
----+----
  1 |  1
  1 |  2
  1 |  3
  1 |  4
  1 |  5

(5 rows)


root@cqlsh:ks> delete from test where ck = 1;

root@cqlsh:ks> insert into test(ck,pk) values (1, 0); -- new minimal value
root@cqlsh:ks> select * from test limit 1;

 ck | pk
----+-------
  1 | 0

(1 rows)

WARN  11:37:39 Read 1 live and 9999 tombstoned cells in ks.test (see tombstone_warn_threshold). 1 columns was reque

为什么当我使用 "LIMIT 1" 执行 SELECT 时,我收到墓碑警告?

行按 pk ASC 排序,此 table (0) 的较低 pk 值是第一行,不会被删除。

我不明白为什么 cassandra 继续扫描我的 table 以获取其他结果(因此获取大量墓碑),因为第一行匹配并且我指定我只想要一行。

如果我没有指定 LIMIT,我本可以理解警告。但是,当第一行与 LIMIT 1 匹配时,扫描整个 table 有什么意义呢?

因为cassandra存储数据的方式。数据存储为单个宽行作为列,即使它通过 cql 看起来像多行。因此,为了到达最后插入的 "row",它还需要读取所有逻辑删除列。

下图

    | 1 | 2 | 3 |...|9999| 0 |
----+---+---+---+---+----+---+
ck=1| T | T | T | T |  T |   |

如您所见,它是集群键 1 下的一行。我用 "T" 标记了逻辑删除列(或行,如果您愿意)。 Cassandra 读取整行,然后为了找到第一个非逻辑删除列,它需​​要循环遍历所有 9999 个逻辑删除列。

当您执行 "select * from test limit 1;" 时,Cassandra 必须转到所有节点并过滤整个 table 以找到第一个活动行。它需要将墓碑流式传输到协调器,因为其他节点可能不同步并且限制 1 将匹配已删除的行。您应该能够通过指定查询来避免这种情况,这样墓碑就无关紧要了,例如 "select * from test where ck=1 and pk < 1;"

好的,所以我想我找到了答案,答案是 cassandra 在限制 1 之后再做一次查找(就像你做限制 2 一样)。

再插入一行:

insert into test(ck,pk) values (1, 1);

现在 select * from test limit 1; 不会触发逻辑删除错误。

但是,如果您执行 LIMIT 2,即使我们有 2 个有效行,它也会触发逻辑删除错误,第一个在 table 顺序中。

问题是为什么cassandra在做(limit+1) lookup。