首页 > 解决方案 > 如何在 Cassandra 的某个时间范围内按字段分组?

问题描述

我有一个包含大约 15 个字段的大型 Cassandra 表,我想创建许多物化视图来支持我的所有查询。基表上的主键是 (CompanyName, ctime),其中 ctime 是 timeuuid。该表记录了在某个时间戳对某个公司网站的每次点击。

例如,我的一个查询包括搜索特定时间范围内(最多一年)最常用的浏览器。

所以我做了

CREATE MATERIALIZED VIEW clicks_by_browser 
    AS SELECT CompanyName, ctime, browsername
    FROM companyclicks
    WHERE CompanyName is not null AND ctime is not null AND browsername is not null
    PRIMARY KEY(CompanyName, ctime, browsername)

但这不起作用。当我进行查询时:

SELECT browsername, count(*) from clicks_by_browser
    WHERE CompanyName='example' and id>=minTimeuuid(...) 
    GROUP BY browsername;

Cassandra 拒绝它,因为“Group by 仅支持按照主键中声明的顺序排列的列组”。所以问题是我在主键中的 browsername 之前声明了 ctime。

所以我尝试将它们的顺序反转为聚类列,

CREATE MATERIALIZED VIEW clicks_by_browser 
    AS SELECT CompanyName, ctime, browsername
    FROM companyclicks
    WHERE CompanyName is not null AND ctime is not null AND browsername is not null
    PRIMARY KEY(CompanyName, browsername, ctime)

但是现在 Cassandra 拒绝了相同的查询,因为在 WHERE 子句中不能限制 ctime,因为前面的列 browsername 不受限制。

那么目前在 Cassandra 中是否无法进行这样的查询?还是我错过了一些明显的东西?

标签: databasecassandra

解决方案


TLDR:这是不可能的。

长答案:
根据 Cassandra JIRA,Cassandra 目前没有在任意列上实现 group by。按多列分组时,只能按主键列在主键中声明的顺序,从第一个开始,按主键列分组。

唯一允许的例外是,如果您使用相等限制限制了前 n 列。请注意,使用“=”限制列是选择一个组,因此该列中没有可分组的内容,这就是 Cassandra 允许这样做的原因。然后,您可以按顺序从下一列开始按剩余列分组(您不能跳过中间的列)。

因此,要按列分组,所有前面的主键列必须受“=”限制或在 group by 子句中。

上述范围查询失败,因为样本列受范围限制,因此仍然有多个组,但不在 group by 子句中。LIKE 和 IN 限制在这种情况下也不起作用。

我认为您可以尝试的最好的事情是在 group by 中包含 timeuuid,然后在应用程序中进行聚合。

SELECT browsername,id, count(*) from clicks_by_browser
    WHERE CompanyName='example' and id>=minTimeuuid(...) 
    GROUP BY id,browsername;

推荐阅读