18

我正在尝试改造一个 SQL 数据库 Cassandra,以便我可以找到与 SQL 查询等效的 Cassandra。我使用 CQL 3 和 Cassandra v1.2。我在 cassandra 中对 db 设计进行了建模,使其支持 order by 子句和非规范化表以支持连接操作。然而,当谈到 DISTINCT、SUM() 和 GROUPBY 等价物时,我在海上

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 中有没有一种方法可以对数据库模式进行建模以支持此类查询?我想不出 Cassandra 有什么办法。如何使用 Cassandra 实现这样的查询?

我读到 Cassandra 上的配置单元层可能会使这些查询工作。我只是想知道这是否是 Cassandra 支持此类查询的唯一方法..?请建议任何其他可能的方法..

4

4 回答 4

26

使用 Cassandra,您可以通过在插入数据时做更多的工作来解决这类问题——这听起来会很慢,但 Cassandra 是为快速写入而设计的,您可能会比您读取数据的次数更多写它,以便在考虑整个系统时有意义。

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

于 2013-06-27T12:42:23.940 回答
22

虽然这是一个老问题,但它在谷歌搜索结果中的出现率很高。所以我想提供一个更新。

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

从 demo2 中选择 DISTINCT (a2),其中 b2='sea'

要实现DISTINCT,您应该定义一个函数和一个聚合门。我将同时调用函数和聚合,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';

SELECT sum(a3), sum(b3) from demo3 where c3='water' and d3='ocean'

SUM开箱即用,可以按您的预期工作。见system.sum

SELECT a1,MAX(b1) FROM demo1 group by a1

GROUP BY是一个棘手的问题。实际上,没有办法按某列对结果行进行分组。但是您可以做的是创建一个map<text, int>并在地图中手动对它们进行分组。基于 Christopher Batey 博客中的一个示例,group-by 和 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 {};

然后按如下方式使用它:

SELECT state_group_and_max(a1, b1) FROM demo1;

笔记

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

参考:

于 2015-10-19T20:55:40.073 回答
16

Cassandra 3.10 现在支持按分区键和集群键分组。您可以参考此链接了解更多详情。

于 2017-02-18T17:39:06.637 回答
10

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

另一种解决方案是自己完成工作。例如,您可以通过从某些行中读取所有数据并求和来求和。或者维护一个 Cassandra 计数器以动态增加。

于 2013-06-27T12:12:57.530 回答