如何选择我的 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;
我的 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;