如何将 NoSQL 数据库设计为 select 按时间戳排序的数据

How to design NoSQL Database to select data order by timestamp

总而言之,我想创建一个 SMACK 架构(Spark、Mesos、Akka、Cassandra 和 Kafka)。我想创建一个入口点,我可以 return 在我的数据库中添加最后 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得到我添加的最后一个元素?

我看到我可以通过这样做来订购 table :

) WITH CLUSTERING ORDER BY (time DESC);

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

由于 Cassandra 需要基于查询的建模方法,我们需要构建一个 table 专门来处理此查询:

SELECT * FROM scala_fireman.fireman 
WHERE temperature > 0 ORDER BY date LIMIT 5 ALLOW FILTERING;

您曾经通过 uuid 查询过吗?如果是这样,那么我们可以构建一个新的 table。否则,您 需要更改您的主键才能使其正常工作。在 ID 列上构建单个 PRIMARY KEY 会严重限制您的查询灵活性(正如您所发现的)。

This is a POC so as many as I can, for the moment I sent 1 million fireman

这将是你的第一个障碍。 Cassandra 只能支持每个分区 20 亿个单元格,而且在此之前它会变慢。因此,我们希望将每个分区的消防员事件数量限制为 "time bucketing." 例如,我将使用 month_bucket,但您应该确定这是否真的适合您的业务需求。

接下来,您想要 ORDER BY 日期,因此我们将其用作聚类键。实际上,由于 date 是一个文本字段,我们将使用 time,因为我确定您不希望结果以 ASCII-betical 顺序返回。 ORDER BY 子句的快速教育是它完全是多余的。您可以 按照您的集群键的预定顺序强制执行它。它永远不需要在查询中。

注意:您收到所见错误的原因是排序顺序只能在 范围内强制执行数据的划分。它不能在结果集上强制执行。

此外,我看到您正在 temperature 上进行开放式范围查询。通常,这是个坏主意(也是您在原始查询中需要 ALLOW FILTERING 的原因)。不过一个分区之内,应该不会太差。只要那个分区不是太大。我们也将集中于此。

当然,多个消防员可能会在同一天同一温度下参与同一事件,因此我们将在末尾添加 uuid 以确保唯一性。您的新主键应如下所示:

    PRIMARY KEY ((month_bucket),time,temperature,uuid))

所以如果试试这个 table 定义:

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!

读一读,看看是否有帮助。