Cassandra CQL带LIMIT的Select计数

18

我创建了一个简单的表格:

CREATE TABLE test (
  "type" varchar,
  "value" varchar,
  PRIMARY KEY(type,value)
);

我向其中插入了5行:

INSERT INTO test(type,value) VALUES('test','tag1')
INSERT INTO test(type,value) VALUES('test','tag2')
INSERT INTO test(type,value) VALUES('test','tag3')
INSERT INTO test(type,value) VALUES('test','tag4')
INSERT INTO test(type,value) VALUES('test','tag5')

我运行了SELECT * from test LIMIT 3,结果如预期。

 type | value
------+------
 test |  tag1
 test |  tag2
 test |  tag3

当我运行 SELECT COUNT(*) from test LIMIT 3 时,它会产生以下结果:
 count
-------
     5

它不应该显示3吗?

根据Datastax文档的说法,指定LIMIT将覆盖默认值10,000。为什么在这种情况下不起作用?如果有影响,我正在使用Cassandra 2.2.5,并通过cqlsh运行了所有查询。

更新:Java驱动程序和CQLSH都经过测试,表明LIMIT确实无法按照文档中的说明工作。如果有任何Datastax员工在阅读,请提供意见。

3个回答

10

我最初的反应是,行数计数器总是在其结果集中返回一行,指示找到的行数。因此,任何大于1的LIMIT都没有影响。

但正如@light所正确指出的那样,文档指出LIMIT应该适用于count(*)。这也有很好的理由。根据这篇博客文章,Cassandra不能获取任何元数据来得出行数,而必须检查每个分区(在每个节点上)才能获得行数。因此,这是一个非常昂贵的操作。

然而,与文档相反,在使用cqlsh或Java驱动程序(v3.0.0)查询C* 2.2.4时,LIMIT子句对报告的行数没有影响。如果超过10,000行,则cqlsh的默认限制为10,000行也无效。即使LIMIT大于10,000也一样。

文档和实现似乎不同步。但我不能说哪一个是错误的。

编辑

@Abhishek Anand引用的票证明了文档是错误的,而不是行为。因此,指定限制为1将计算所有行。这是期望的行为。


如果SELECT COUNT总是返回1行,那么在SELECT COUNT查询中使用LIMIT子句是无用的,不是吗?为什么Datastax文档会特别给出像SELECT COUNT(*) FROM big_table LIMIT 50000;这样的例子呢? - light
@light,嗯,你是对的。文档建议当与LIMIT子句组合使用时,计数应该返回3.这篇文章解释了为什么将限制应用于计数是一个好的选择。我会在我的实例上进行测试(C* v 2.2.4)。那么您的C*版本是多少? - Ralf
我正在使用Cassandra v2.2.5版本。 - light
@light,真遗憾。;-) 我希望你使用的是v3.x版本。该版本的存储引擎已经完全重新设计。额外元数据的存在可能允许他们消除将LIMIT应用于count()查询的限制。 - Ralf
当v3变得更加稳定并得到更好的支持,即各种语言的驱动程序得到更新时,我可能会升级到v3。希望会有更好的文档,这样我们就不必为这些“异常”而苦恼了 :) - light
感谢您的更新。也许我们需要等待官方消息的澄清。无论如何,您原始答案中的前提条件,即“LIMIT”不适用于“SELECT COUNT”中的计数值似乎是错误的。为了使未来的读者受益,建议将其删除。 - light

10

这是cassandra中的一个漏洞,版本2.2.x受到影响。

https://issues.apache.org/jira/browse/CASSANDRA-8216

他们已将其标记为已修复,但显然这已经传播到超出修复版本的版本。

无论如何,您的假设/想法完全正确。 必须在cassandra的count(*)上应用limit关键字,并且它在我使用的版本3.2.4和2.1.x中起作用。


我有cassandra [cqlsh 5.0.1 | Cassandra 3.6 | CQL spec 3.4.2 | Native protocol v4]。当我使用此查询 - SELECT COUNT(*) from kwhhourlyconsumption LIMIT 3; 我得到错误的输出,即87,并显示警告-“在没有分区键的情况下使用聚合查询”。请让我知道是否有遗漏的内容。@Abhishek Anand - Tejas Ratunawar

2

Limit子句用于限制结果中的行数。count(*)仅返回一个包含总行数的单行记录。

"limit 3"不会影响从count(*)分析的出现次数,如果您想要这样做,您必须使用"where"。


感谢您的回答。如果SELECT COUNT总是返回1行,那么在SELECT COUNT查询中使用LIMIT子句是无用的,不是吗?为什么Datastax文档会明确给出像SELECT COUNT(*) FROM big_table LIMIT 50000;这样的示例呢? - light
你是指参考这份文档吗?--> "SELECT COUNT() FROM big_table LIMIT 50000; SELECT COUNT() FROM big_table LIMIT 200000;" 如果数据库中有105,291行,则以上语句的输出结果应为:50000和105291。我认为他们可能存在混淆。 - mariettièllo
那么Datastax的文档是错误的吗? - light
这个问题的答案也表明,使用LIMIT也适用于SELECT COUNT:https://dev59.com/qV_Va4cB1Zd3GeqPPxjy?rq=1 - light
我之前不知道,但是示例表明你只能使用这个函数来增加限制,而不能减少。也许这就是为什么你的例子不起作用的原因。 - mariettièllo
也许是这样,但在文档或我能找到的任何地方都不是很清楚。无论如何,“LIMIT”与“SELECT COUNT”不兼容的前提似乎是不正确的,这正是你的答案所暗示的。 - light

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