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排序,此表(0)的较低pk值是第一行,不会被删除。
我不明白为什么cassandra继续扫描我的表以获取其他结果(因此获取了很多墓碑),因为第一行匹配并且我指定我只想要一行。
如果我没有指定LIMIT,我本可以理解警告。但是当第一行与LIMIT 1匹配时,扫描整个表是什么意思?
答案 0 :(得分:3)
因为cassandra存储数据的方式。数据作为列存储为单个宽行,即使它像多行一样通过cql查找。因此,为了到达最后插入的“行”,它还需要读取所有逻辑删除的列。
以下是插图
| 1 | 2 | 3 |...|9999| 0 |
----+---+---+---+---+----+---+
ck=1| T | T | T | T | T | |
正如您所看到的,它是一个聚类键下的一行1.我用“T”标记了逻辑删除的列(如果您愿意,还是行)。 Cassandra读取整行,然后为了找到第一个非逻辑删除的列,它需要遍历所有9999个逻辑删除的列。
答案 1 :(得分:0)
当您执行“select * from test limit 1;”时,Cassandra必须转到所有节点并过滤整个表以查找第一个实时行。它需要将逻辑删动流式传输到协调器,因为其他节点可能不同步,并且限制1将匹配已删除的行。您应该能够通过指定查询来避免这种情况,使得墓碑无关紧要,例如“select * from test where ck = 1 and pk&lt; 1;”
答案 2 :(得分:0)
好的,所以我觉得我找到了答案,答案是cassandra在限制1之后再做一次查找(就像你确实限制了2)。
再插入一行:
insert into test(ck,pk) values (1, 1);
现在select * from test limit 1;
不会触发逻辑删除错误。
但是,如果你执行LIMIT 2,即使我们有2个有效行,它也会触发逻辑删除错误,首先是表顺序。
为什么cassandra正在进行(限制+ 1)查询是个问题。