如何设计NoSQL数据库以按时间戳选择数据顺序

时间:2019-04-29 15:06:30

标签: cassandra nosql cassandra-3.0

总结一下,我想创建一个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以获得我添加的最后n个元素?

我看到可以通过执行以下操作来对表格进行排序:

) WITH CLUSTERING ORDER BY (time DESC);

但是要做到这一点,我需要将时间更改为主键,但是同时添加了一些数据,因此我无法将其设置为主键。

1 个答案:

答案 0 :(得分:3)

由于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字母顺序排列。对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撰写了关于结果集排序的文章,并在其中演示了这些建模技术的用法。四年后,它仍然非常重要(尤其是对于像这样的问题):

We Shall Have Order!

阅读,看看是否有帮助。