总结一下,我想创建一个SMACK架构(Spark,Mesos,Akka,Cassandra和Kafka)。我想做一个入口点,我可以在我的数据库中返回50个最后一个元素添加。这是我的数据库:
create table fireman
(
uuid uuid primary key,
date text,
heartrate int,
id text,
location text,
ratecommunication int,
temperature int,
time timestamp
);
我试着查询一下:
SELECT * FROM scala_fireman.fireman WHERE temperature > 0 ORDER BY date LIMIT 5 ALLOW FILTERING ;
但我得到了这个错误:
ORDER BY is only supported when the partition key is restricted by an EQ or an IN.
所以我的问题是SELECT如何获得我添加的最后一个元素?
我看到我可以通过这样做来订购表:
) WITH CLUSTERING ORDER BY (time DESC);
但要做到这一点,我需要将时间更改为主键,但有些数据会同时添加,因此我无法将其设置为主键。
由于Cassandra需要基于查询的建模方法,我们需要专门构建一个表来处理这个查询:
SELECT * FROM scala_fireman.fireman
WHERE temperature > 0 ORDER BY date LIMIT 5 ALLOW FILTERING;
你有没有问过uuid
?如果是这样,那么我们可以构建一个新表。如果没有,您将需要更改主键才能使其正常工作。在ID列上构建单个PRIMARY KEY会严重限制您的查询灵活性(正如您所发现的那样)。
这是一个尽可能多的POC,目前我已派出100万名消防员
这将是你的第一个障碍。 Cassandra每个分区只能支持20亿个单元,而且在此之前很久就会变慢。因此,我们希望通过“时间分组”来限制每个分区的消防员事件数量。例如,我将使用month_bucket
,但您应该确定这是否真的适合您的业务需求。
接下来,你想要ORDER BY
日期,所以我们将它用作聚类键。实际上,由于date
是一个文本字段,我们将使用time
,因为我确定你不希望以ASCII-betical顺序返回结果。关于ORDER BY
条款的快速教育,就是它完全是多余的。您只能按照群集密钥的预定顺序强制执行该操作。它不应该在查询中。
注意:您收到错误的原因是,排序顺序只能在数据分区中强制执行。它不能在结果集上强制执行。
另外,我看到你在temperature
上做了一个开放式的范围查询。通常,这是一个坏主意(以及您在原始查询中需要ALLOW FILTERING
的原因)。但在一个分区内,它应该不会太糟糕。只要那个分区不是太大。我们也将集中于此。
当然,有可能多个消防员可以在相同的温度下参与相同温度的事件,因此我们将在最后添加uuid
以强制执行唯一性。您的新主键应如下所示:
PRIMARY KEY ((month_bucket),time,temperature,uuid))
所以如果尝试这个表定义:
create table fireman_events_by_date_and_temp (
uuid uuid,
month_bucket int,
date text,
heartrate int,
id text,
location text,
ratecommunication int,
temperature int,
time timestamp,
PRIMARY KEY ((month_bucket),time,temperature,uuid))
WITH CLUSTERING ORDER BY (time DESC, temperature ASC, uuid ASC);
现在,如果我加载一些数据并运行您的查询:
> SELECT time,temperature,heartrate,location
FROM fireman_events_by_date_and_temp
WHERE month_bucket=201904
AND temperature > 0
LIMIT 5
ALLOW FILTERING;
time | temperature | heartrate | location
---------------------------------+-------------+-----------+----------
2019-04-30 13:40:03.253000+0000 | 644 | 144 | SF
2019-04-30 13:39:51.944000+0000 | 644 | 144 | SF
2019-04-30 13:39:39.859000+0000 | 644 | 144 | SF
2019-04-30 13:39:30.331000+0000 | 644 | 144 | SF
2019-04-30 13:39:15.945000+0000 | 644 | 144 | NY
(5 rows)
通常,我不建议使用ALLOW FILTERING
。但只要您查询分区键(month_bucket
),所有数据仍应由同一节点提供服务。
另外,我在2015年写了关于Cassandra中结果集排序的这篇文章,并在其中演示了这些建模技术的使用。四年后它仍然非常相关(特别是对于这样的问题):
给它一个阅读,看看它是否有帮助。