如何选择我的 Cassandra 密钥以进行正确的默认排序?

How to choose my Cassandra key for correct default sorting?

我的 table samples 由这样的列组成:

id : uuid
created : timestamp
device : ascii
reading : float

我的大部分查询都是在所有设备上获取最新的 n 样本,因此我希望这是默认排序:

SELECT * FROM samples LIMIT 1024

我还希望能够有效地获取给定 设备的最新 n 样本:

SELECT * FROM samples WHERE device = 'abc' LIMIT 1024

我应该如何设计我的分区键来实现这一点?

对于 Cassandra,建议采用基于查询的建模方法。为此,每个需要支持的查询都有一个 table 并不少见。

SELECT * FROM samples LIMIT 1024

对于第一个查询,我立即看到的最大问题是没有 WHERE 子句。这将导致 Cassandra 必须检查每个节点以构建结果集;绝对不希望发生这种情况。但听起来您最关心的是最近的数据,或者特定日期的数据。为此,我们需要基于 date/time 组件创建分区键或“存储桶”。

注意,这也是必需的,因为从多个分区中检索的数据无法排序。

为此,数据的基数很重要。您正在选择前 1024 名,所以一天内获得那么多是很常见的吗?或者是一个多星期?现在,我将假定为“天”并添加一个 day_bucket 列。

CREATE TABLE samples_by_day (
  id uuid,
  created timestamp,
  device ascii,
  reading float,
  day_bucket bigint,
  PRIMARY KEY (day_bucket,created,id)
) WITH CLUSTERING ORDER BY (created DESC, id ASC);

此主键定义将按天对数据进行分区(例如:20200710)。在这些分区中,数据将按 created 降序排列(最新的排在最前面)。添加 id 列以确保唯一性。这将支持以下查询:

SELECT * FROM samples_by_day
WHERE day_bucket = 20200710 LIMIT 1024;

对于多天,您可以 运行 多次查询。您甚至可以按周或按月“分桶”,前提是这不会超出 20 亿 cells/partition 限制的界限。

支持此查询:

SELECT * FROM samples
WHERE device = 'abc' LIMIT 1024;

...容易得多

CREATE TABLE samples_by_device (
  id uuid,
  created timestamp,
  device ascii,
  reading float,
  day_bucket bigint,
  PRIMARY KEY (device,created,id)
) WITH CLUSTERING ORDER BY (created DESC, id ASC);

这可行,但很可能 运行 出现“未绑定行增长”的问题。基本上,如果不断为每个设备添加设备样本,分区大小最终会达到最大值。因此,可能需要添加 day_bucket(或任何适合您的时间段)作为附加分区键:

PRIMARY KEY ((device,day_bucket),created,id)

有了这个改变,查询也需要改变:

SELECT * FROM samples_by_device
WHERE device = 'abc' AND day_bucket = 20200710 LIMIT 1024;