使用SELECT LIMIT 1进行墓碑警告

时间:2015-01-26 11:45:28

标签: cassandra

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匹配时,扫描整个表是什么意思?

3 个答案:

答案 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)查询是个问题。