MAX(),DISTINCT和Cassandra的分组

时间:2013-06-27 11:40:07

标签: nosql cassandra cql cql3 nosql-aggregation

我正在尝试重新构建一个SQL数据库Cassandra,这样我就可以找到与SQL查询等效的Cassandra。我使用CQL 3和Cassandra v1.2。我在cassandra中对db设计进行了建模,以便它支持子句和非规范化表的顺序以支持连接操作。但是,当谈到DISTINCT,SUM()和GROUPBY equvalents

时,我在海上
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上的hive层可能会使这些查询起作用。我只是想知道这是否是在Cassandra中支持此类查询的唯一方法..?请建议任何其他可能的方法..

4 个答案:

答案 0 :(得分:26)

使用Cassandra,你可以通过在插入数据时做更多工作来解决这些问题 - 这听起来似乎很慢,但Cassandra专为快速写入而设计,你可能会更多地阅读数据比你写它的时间所以当你考虑整个系统时它是有意义的。

我无法确切地告诉您如何创建表格以模拟您的问题,因为它将在很大程度上取决于细节。您需要确定一个架构,使您可以在不执行任何即时聚合的情况下获取数据。考虑如何在RDBMS中为查询创建视图,然后尝试思考如何将数据直接插入到这些视图中,而不是插入到基础表中。这就是你在Cassandra中塑造事物的方式。

答案 1 :(得分:21)

虽然这是一个老问题,但它在Google搜索结果中显得相当高。所以我想提供一个更新。

Cassandra 2.2+支持用户定义的功能和用户定义的聚合。 警告:这并不意味着您不再需要进行数据建模(正如@Theo指出的那样),而只是让您在检索时稍微预处理数据。

  

SELECT DISTINCT(a2)FROM demo2其中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 {};

然后按如下方式使用它:

SELECT uniq(a2) FROM demo2 where b2='sea';
  

从demo3中选择sum(a3),sum(b3),其中c3 =&#39; water&#39;和d3 =&#39;海洋&#39;

SUM开箱即用,可以按照您的预期运行。请参阅system.sum

  

从a1

中选择a1,MAX(b1)FROM demo1组

GROUP BY是一个棘手的问题。实际上,没有办法按某些列对结果行进行分组。但您可以做的是创建map<text, int>并在地图中手动对它们进行分组。基于Christopher Batey的博客,分组和最大的例子

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;

注释

  • 如上所述,您仍需要花一些时间进行数据建模,不要过度使用这些功能
  • 您必须在enable_user_defined_functions=true中设置cassandra.yaml以启用功能
  • 您可以重载函数以支持按不同类型的列进行分组。

参考文献:

答案 2 :(得分:12)

Cassandra 3.10现在支持Group by parition key和clustering key。您可以参考this link了解更多详情。

答案 3 :(得分:11)

Cassandra不支持此类操作。您可以在顶部使用Hive之类的东西,或者使用Acunu的(非免费)产品,它可以满足您的需求。

另一种解决方案是自己完成工作。例如,您可以通过读取某些行中的所有数据并求和来对事物求和。或者保持Cassandra计数器在运行中增加。