我正在尝试重新构建SQL数据库Cassandra,这样,我就可以为SQL查询找到Cassandra等效数据库。我使用CQL3和Cassandra v1.2。我在cassandra中对数据库设计进行了建模,以便它支持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,当您插入数据时,您可以通过做更多的工作来解决这些问题——这听起来很慢,但Cassandra是为快速写入而设计的,您可能会读取数据的次数比写入数据的次数多得多,因此当您考虑整个系统时,这是有意义的。
我不能确切地告诉你如何创建表来为你的问题建模,因为这在很大程度上取决于细节。您需要制定一个模式,使您能够在不执行任何动态聚合的情况下获取数据。想想如何在RDBMS中为查询创建视图,然后试着想想如何将数据直接插入到这些视图中,而不是插入到底层表中。这就是你在《卡桑德拉》中塑造事物的方式。
尽管这是一个老问题,但它在谷歌搜索结果中的出现率相当高。所以我想更新一下。
Cassandra 2.2+支持用户定义的函数和用户定义的聚合警告:这并不意味着你不必再进行数据建模(正如@Theo所指出的那样),它只是允许你在检索时对数据进行轻微的预处理。
从demo2选择差异(a2),其中b2="ea"
要实现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="水",d3="海洋"
SUM
是开箱即用的,可以按照您的期望工作。参见system.sum
。
通过a1 从demo1组选择a1,MAX(b1)
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;
备注
- 正如上面提到的,您仍然需要在数据建模上投入一些时间,不要过度使用这些功能
- 您必须在
cassandra.yaml
中设置enable_user_defined_functions=true
才能启用这些功能 - 您可以重载函数以支持按不同类型的列进行分组
参考文献:
- Christopher Batey的伟大UDF和UDA示例
- UDF和UDA的数据税文档
- Cassandra 3.0中的用户定义函数(Planet Cassandra博客)
Cassandra 3.10现在支持分组键和集群键分组。您可以参考此链接了解更多详细信息。
Cassandra不支持这样的操作。你可以在上面使用Hive之类的东西,或者Acunu的(非免费)产品可以满足你的需求。
另一个解决方案是自己做这项工作。例如,您可以通过读取某些行中的所有数据并求和来求和。或者保持一个卡桑德拉计数器在飞行中递增。