使用CQL3迭代Cassandra宽行

10
我该如何使用CQL3获取一系列复合列?
考虑以下情况:
CREATE TABLE Stuff (
    a int,
    b text,
    c text,
    d text,
    PRIMARY KEY (a,b,c)
);

在Cassandra中,这实际上创建了一个带有整数行(a的值)和由b和c的值以及字面字符串“d”组成的CompositeColumns的ColumnFamily。当然,所有这些都被CQL3所覆盖,以便我们认为我们正在插入单个数据库行...但我偏离了主题。
考虑以下一组输入:
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','P','whatever0');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','Q','whatever1');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','R','whatever2');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','S','whatever3');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'A','T','whatever4');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','P','whatever5');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','Q','whatever6');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','R','whatever7');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','S','whatever8');
INSERT INTO Stuff (a,b,c,d) VALUES (1,'B','T','whatever9');

在我的当前使用情况下,我想一次读取所有“Stuff”的值,每次读取n个值。我该怎么做?这是我目前使用的n=4的方法:
SELECT * FROM Stuff WHERE a=1 LIMIT 4;

"并如预期,我得到了:

"

 a | b | c | d
---+---+---+-----------
 1 | A | P | whatever0
 1 | A | Q | whatever1
 1 | A | R | whatever2
 1 | A | S | whatever3

我遇到的问题是如何获取接下来的4个?这是我的尝试:
SELECT * FROM Stuff WHERE a=1 AND b='A' AND c>'S' LIMIT 4;

这无法工作,因为我们已经限制b等于'A' - 这是一个合理的做法!但我在CQL3语法中找不到任何允许我继续迭代的方法。我希望我能做类似以下的操作:

SELECT * FROM Stuff WHERE a=1 AND {b,c} > {'A','S'} LIMIT 4;

我该如何达到我想要的结果?也就是说,我如何让CQL3返回:
 a | b | c | d
---+---+---+-----------
 1 | A | T | whatever0
 1 | B | P | whatever1
 1 | B | Q | whatever2
 1 | B | R | whatever3

自己注意:有同样问题的其他人 - JnBrymn
4个回答

5

4
为了让我理解,我安装了Cassandra 2.0.6并使用cqlsh尝试在一个包含约20K记录的CF上执行select查询,没有指定limit。我的查询结果是10K,并显示信息“**Default LIMIT of 10000 was used. Specify your own LIMIT clause to get more results.**”那么自动分页在哪里,或者是我做/理解错什么了? - Shri

4

阅读完CQL3文档后,我没有找到实现所需效果的方法。

但是,您可以通过一系列CQL查询模拟所需的效果。考虑我想每次以4个为单位浏览上述模型中的项目。很容易获取前4个:

SELECT * FROM a = 1 LIMIT 4;

但是没有办法在单个查询中获取接下来的4个。但我可以分步骤执行。上面查询的最后一个项目是

 a | b | c | d
---+---+---+-----------
 1 | A | S | whatever3

所以我可以发出一个查询,从这里开始获取所有内容,直到下一个值为b

SELECT * FROM a = 1 WHERE b='A' and c>'S' LIMIT 4;

在这种情况下,我将获得一个单独的CQL3行:

 a | b | c | d
---+---+---+-----------
 1 | A | T | whatever4

现在,如果我得到了4行,我就会达到限制,下一次我将从该集合的最后一个元素重新开始。但现在我只有一行。

因此,为了获取其余的三行,我从那个点开始迭代并获取剩余的三行:

SELECT * FROM a = 1 WHERE b > 'A' LIMIT 3;

我会使用同样的算法一直进行扫描,直到我满意为止。

在上面的例子中,主键由3个元素组成,这意味着在Cassandra中,列名是由2个元素的CompositeColumns组成的(...基本上是这样,但这里的区别无关紧要)。而且,由于CompositeColumns有2个元素,你必须进行2次查询,就像我在这里演示的一样。总的来说,如果主键有n个元素,则您将不得不进行n-1次查询,以模拟对CQL表(即Cassandra行)的扫描。


更新:事实上,CQL3没有服务器端游标(参见“CQL3分页”部分这里),如果您想要伪造它,您必须使用上述描述的东西(在该链接中进一步阅读,以看到我基本思路的详细说明)。
然而,在Cassandra 2中将有一个关于服务器端游标的JIRA问题,并且已经存在于Cassandra 2 Beta中。
还有一个相关的JIRA问题,它将使实现客户端游标变得更加容易,就像我上面所暗示的那样。但它仍未解决。

更新2:JIRA问题已经修复。

现在您可以使用元组/向量语法查询,其中 WHERE (c1, c2) > (1, 0)


我不建议使用LIMIT子句,而是应该使用主键,或许可以借助元表来实现。我曾经遇到过严重的性能下降问题,我认为这是分布式数据库的本质所致——因为需要协调所有节点才能确定何时达到了LIMIT限制,所以必须在返回结果集之前先统计所有行数。 - John

0
你想做的是在Cassandra中获取分页内容。CQL3不支持此功能。 你应该创建一个适合比较的列,即用于小于、大于操作的列,并且该列应形成增加/减少的序列。正如jorgebg上面注意到的那样,b+c的连接将适合这个需求。

-1

select * from stuff where a = 1 and (b,c) > ('A','S') limit 4;

从东西中选择*,其中a = 1且(b,c)>('A','S')限制4;


通常情况下,如果回答中包含代码的意图和为什么能够解决问题并且不会引入其他问题的解释的话,回答将更加有用。 (该帖子被至少一位用户标记,可能是因为他们认为没有解释的答案应该被删除。) - Nathan Tuggy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接