我们有一个包含大量时间序列数据的表。可能我们必须在该表中每毫秒存储几个条目。为了满足这些要求,表格如下所示
CREATE TABLE statistic (
name text,
id uuid,
start timestamp,
other_data ...,
PRIMARY KEY (name, start, id)
) WITH CLUSTERING ORDER BY (start DESC);
如您所见,该表由两个聚类键组成,start
存储数据到达的时间,id
的目的是避免数据在同一时间到达时被覆盖
现在没关系,我们可以进行范围查询,例如
SELECT * FROM statistic WHERE name ='foo' AND start >= 1453730078182
AND start <= 1453730078251;
但我们还需要能够在查询中添加其他搜索参数,例如
SELECT * FROM statistic WHERE name = 'foo'
AND start >= 1453730078182 AND start <= 1453730078251 AND other_data = 'bar';
这当然不起作用,因为other_data
不是主键的一部分。如果我们将它添加到主键,我们会收到以下错误
InvalidRequest:code = 2200 [无效查询] message =“PRIMARY KEY列”other_data“无法限制(前一列”start“受非EQ关系限制)”
那也没关系,这不是Cassandra
的工作方式(我认为)。
我们解决问题的方法是使用上面提到的(第一个)范围查询选择所需的(时间序列)数据,然后在我们的Java应用程序中过滤数据。这意味着我们浏览列表并将我们在Java应用程序中不需要的所有数据踢出去。一个条目没有太多数据,但在最坏的情况下我们会谈论数百万行。
现在我有两个问题:
答案 0 :(得分:0)
这当然不起作用,因为other_data不是主键的一部分。如果我们将它添加到主键,我们会收到以下错误
这是 other_data 列上二级索引的最佳位置。在您的情况下,此索引将缩放,因为您始终提供分区键(名称),因此Cassandra不会命中群集中的所有节点。
使用 other_data 上的辅助索引,您的第二个SELECT语句将是可能的。
现在您的数据模型还有另一个问题,即分区大小。实际上,如果您每个名称每秒插入几个条目,这将无法扩展,因为每个名称的分区将增长得非常快......
如果插入分布在不同的分区键(不同的名称)上,那么它很好