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。
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。