Cassandra与过滤器分组

时间:2017-05-17 19:20:10

标签: cassandra

我每分钟都有一张事件表。我希望能够按时间段过滤这些事件,并且还可以汇总小时/天/等的数据。

我的数据模型:

create table min_dev_data (
device TEXT,
event_time BIGINT,
hour BIGINT,
day BIGINT,
value DOUBLE,
PRIMARY KEY ((device), event_time)
)

CREATE MATERIALIZED VIEW hour_dev_data AS
SELECT device, event_time, hour, value
FROM min_dev_data
WHERE hour IS NOT NULL AND value IS NOT NULL 
      and event_time IS NOT NULL AND device IS NOT NULL
PRIMARY KEY ((device), hour, event_time)

我的查询是

select hour, sum(value) 
from hour_dev_data 
where device = 'tst' and event_time < 149000000 group by device, hour;

失败并出错 code = 2200 [无效查询]消息=&#34; PRIMARY KEY列&#34; event_time&#34;不能被限制为前一列&#34;小时&#34;不受限制&#34;

使其工作的唯一方法是添加ALLOW FILTERING,这是不可预测的。

如何更改数据模型以解决查询问题并避免使用ALLOW FILTERING模式?

2 个答案:

答案 0 :(得分:1)

您必须主动产生这些结果:

 var opt = { minZoom: 6, maxZoom: 9 };
 map.setOptions(opt);

每个表仅满足一个粒度。

每小时您都会使用以下内容查询每个设备的最新小时数据的分钟数据:

create table min_dev_data (
    device TEXT,
    event_time BIGINT,
    hour BIGINT,
    day BIGINT,
    value DOUBLE,
    PRIMARY KEY ((device), event_time)
) WITH CLUSTERING ORDER BY (event_time DESC);

create table hour_dev_data (
    device TEXT,
    hour BIGINT,
    day BIGINT,
    event_time BIGINT,
    value DOUBLE,
    PRIMARY KEY ((device), event_time)
) WITH CLUSTERING ORDER BY (event_time DESC);

create table day_dev_data (
    device TEXT,
    day BIGINT,
    event_time BIGINT,
    value DOUBLE,
    PRIMARY KEY ((device), event_time)
) WITH CLUSTERING ORDER BY (event_time DESC);

在应用程序级别求和并将此值存储到小时表中:

SELECT * FROM min_dev_data WHERE device = X AND event_time < YYYY

每天查询小时表以生成更多聚合数据:

INSERT INTO hour_dev_data (device, hour, day, event_time, value) VALUES (....);

在应用程序级别求和并将此值存储到日期表中。

请考虑添加某种形式的分组,因为在一分钟的间隔内,在两分钟内,分钟表将具有宽分区。如果您以相反的顺序(就像我所做的那样)保持表并且仅查询过去几个小时,这应该不是问题。但是如果你想要及时查询,那么你必须在表格中使用bucketing。

答案 1 :(得分:1)

我认为你已经有了相当正确的事情,但是你需要在event_time上更改过滤器,以便成为hour的过滤器。

select hour, sum(value)  
from hour_dev_data  
where device = 'tst' and hour < 1500000000 
group by device, hour;

当您对event_time进行过滤时,您隐式要求对该行进行完整扫描,因为event_time在一小时后聚集。要按event_time进行过滤,需要检查每个单元格以检查event_time。当您按hour进行过滤时,它首先位于群集密钥中,因此可以对其进行有效扫描和过滤。有关详情,请参阅ALLOW FILTERING上的这篇帖子。

我同意xmas79你可能希望在一定程度上进行分组,可能是按月或根据你的事件频率按月或按年。如果你总是要寻找最新的值,那么将聚类键排序设置为desc也可能会有所帮助:

CREATE MATERIALIZED VIEW hour_dev_data3 AS
SELECT device, event_time, hour, value
FROM min_dev_data
WHERE hour IS NOT NULL AND value IS NOT NULL 
      and event_time IS NOT NULL AND device IS NOT NULL
PRIMARY KEY ((device), hour, event_time)
WITH CLUSTERING ORDER BY (hour DESC);

调度聚合(如xmas79建议)会更有效,因为总和只执行一次,而不是每次读取完成时总和,但它会增加更多的维护负担,物化视图会为您处理它。