Nosql Cassandra中的MAX()、DISTINCT和group by
我正在尝试重新构建一个SQL数据库Cassandra,这样,我就可以找到SQL查询的Cassandra等价物。我使用CQL3和CassandraV1.2。我用cassandra对db设计进行建模,以便它支持order by子句和非规范化的表来支持join操作。然而,当涉及到DISTINCT、SUM和GROUPBY等值时,我却不知所措Nosql Cassandra中的MAX()、DISTINCT和group by,nosql,cassandra,cql,cql3,nosql-aggregation,Nosql,Cassandra,Cql,Cql3,Nosql Aggregation,我正在尝试重新构建一个SQL数据库Cassandra,这样,我就可以找到SQL查询的Cassandra等价物。我使用CQL3和CassandraV1.2。我用cassandra对db设计进行建模,以便它支持order by子句和非规范化的表来支持join操作。然而,当涉及到DISTINCT、SUM和GROUPBY等值时,我却不知所措 SELECT a1,MAX(b1) FROM demo1 group by a1. SELECT DISTINCT (a2) FROM demo2 where b2
SELECT a1,MAX(b1) FROM demo1 group by a1.
SELECT DISTINCT (a2) FROM demo2 where b2='sea'
SELECT sum(a3), sum(b3) from demo3 where c3='water' and d3='ocean'
这对我过去几天的工作来说就像是一场闹剧。在Cassandra中是否有一种方法可以对db模式进行建模以支持此类查询?在卡桑德拉我想不出任何办法。如何使用Cassandra实现这些查询
我听说Cassandra上的蜂巢层可能会使这些查询工作。我只是想知道这是否是在Cassandra中支持此类查询的唯一方法。。?请建议其他可能的方法。卡桑德拉不支持这样的操作。您可以在顶部使用Hive之类的产品,或者Acunu的非免费产品可以满足您的需要
另一个解决办法是自己做这项工作。例如,您可以通过读取特定行中的所有数据并求和来求和。或者维护一个Cassandra计数器以动态递增。使用Cassandra,您可以通过在插入数据时做更多的工作来解决此类问题-这听起来很慢,但Cassandra专为快速写入而设计,你可能会比你写的数据多读几遍,所以当你考虑整个系统时,它是有意义的。< /P>
我不能确切地告诉您如何创建表来模拟问题,因为这在很大程度上取决于细节。您需要制定一个模式,使您能够在不执行任何动态聚合的情况下获取数据。考虑如何在RDBMS中为查询创建视图,然后尝试考虑如何将数据直接插入到这些视图中,而不是插入到基础表中。这就是你在Cassandra中建模的方式。虽然这是一个老问题,但它在谷歌搜索结果中出现的频率相当高。所以我想更新一下 Cassandra 2.2+支持用户定义函数和用户定义聚合。警告:这并不意味着你不再需要像@Theo所指出的那样进行数据建模,而是允许你在检索数据时稍微预处理数据 从演示2中选择不同的a2,其中b2='sea' 要实现DISTINCT,您应该定义一个函数和一个agreggate。我将调用函数和聚合uniq,而不是distinct,以强调它是用户定义的
CREATE OR REPLACE FUNCTION uniq(state set<text>, val text)
CALLED ON NULL INPUT RETURNS set<text> LANGUAGE java
AS 'state.add(val); return state;';
CREATE OR REPLACE AGGREGATE uniq(text)
SFUNC uniq STYPE set<text> INITCOND {};
从演示3中选择suma3、sumb3,其中c3='water'和d3='ocean'
SUM是开箱即用的,正如您所期望的那样工作。见system.sum
按a1从demo1分组中选择a1、MAXb1
分组是个棘手的问题。实际上,没有办法按某个列对结果行进行分组。但您可以做的是创建一个地图,并在地图中手动将它们分组。根据Christopher Batey的博客group by and max中的一个示例:
CREATE OR REPLACE FUNCTION state_group_and_max(state map<text, int>, type text, amount int)
CALLED ON NULL INPUT
RETURNS map<text, int>
LANGUAGE java AS '
Integer val = (Integer) state.get(type);
if (val == null) val = amount; else val = Math.max(val, amount);
state.put(type, val);
return state;
' ;
CREATE OR REPLACE AGGREGATE state_group_and_max(text, int)
SFUNC state_group_and_max
STYPE map<text, int>
INITCOND {};
笔记
正如上面提到的,您仍然需要在数据建模上投入一些时间,不要过度使用这些特性
您必须在cassandra.yaml中设置enable_user_defined_functions=true才能启用这些功能
可以重载函数以支持按不同类型的列进行分组。
参考资料:
和
Cassandra 3.10现在支持分组键和集群键。有关更多详细信息,请参阅。我确实想到了用于实现求和方法的计数器选项。但是我必须为许多列维护计数器,这些列可以有许多值。但是,这似乎是cassandra支持求和函数的唯一方法。。谢谢你的投入……谢谢你,这对我很有帮助。不管怎样,我还是在这里问问吧。在我的例子中,我有一个计数器列族,我想得到一些带有max计数器的字段,我想知道为什么默认的max函数适用于计数器数据类型,但当我使用您的UDA时它不起作用。它说它需要int,而计数器数据类型没有归类为int。你知道吗?谢谢。您好,根据柜台类型是独一无二的。这意味着您也必须为计数器类型重载函数。例如,自定义max函数将是:创建函数maxCustomcurrent counter,在NULL输入上调用的候选计数器将计数器语言java作为“if current==NULL return candidate”;否则返回Math.maxcurrent,candidate;'创建聚合maxCustomcounter SFUNC maxCustom STYPE计数器INITCOND null;
CREATE OR REPLACE FUNCTION state_group_and_max(state map<text, int>, type text, amount int)
CALLED ON NULL INPUT
RETURNS map<text, int>
LANGUAGE java AS '
Integer val = (Integer) state.get(type);
if (val == null) val = amount; else val = Math.max(val, amount);
state.put(type, val);
return state;
' ;
CREATE OR REPLACE AGGREGATE state_group_and_max(text, int)
SFUNC state_group_and_max
STYPE map<text, int>
INITCOND {};
SELECT state_group_and_max(a1, b1) FROM demo1;