Cassandra 需要关于适当的主键结构的建议

Cassandra 需要关于适当的主键结构的建议,cassandra,database,nosql,Cassandra,Database,Nosql,我有很多时间序列数据要存储在Cassandra数据库中。由于我只能对主键中的字段执行WHERE子句,因此我需要一些关于如何根据我需要查询它的方式进行布局的建议 我的数据采用以下格式: SYSTEM_SERIAL_NUMBER,DEVICE_ID,TIMESTAMP,...OTHER COLUMNS 每个序列号都有多个设备,每个设备都有数千个时间戳,因此我唯一标识每组数据的主键必须包括所有三个 基本上,我将对这些数据执行两种类型的查询 从表中选择*,其中系统序列号为'X',设备id为'X',时间

我有很多时间序列数据要存储在Cassandra数据库中。由于我只能对主键中的字段执行
WHERE
子句,因此我需要一些关于如何根据我需要查询它的方式进行布局的建议

我的数据采用以下格式:

SYSTEM_SERIAL_NUMBER,DEVICE_ID,TIMESTAMP,...OTHER COLUMNS
每个序列号都有多个设备,每个设备都有数千个时间戳,因此我唯一标识每组数据的主键必须包括所有三个

基本上,我将对这些数据执行两种类型的查询

从表中选择*,其中系统序列号为'X',设备id为'X',时间戳为
(在一定范围内)

从表中选择*,其中系统序列号='X'和时间戳
(在一定范围内)

第二个是更可能的查询,因为我通常会在应用程序中输入一个时间范围,并且我希望看到来自给定序列号的每个设备的数据。但是我不能把设备名漏掉,因为您需要serial/device/timestamp才能唯一地标识整行

我已尝试按如下方式创建表:

CREATE TABLE devices (
system_serial_number text,
device_id int,
time_stamp timestamp,
...,
PRIMARY KEY ((system_serial_number,device_id),time_stamp)
);
以及:

CREATE TABLE devices (
system_serial_number text,
device_id int,
time_stamp timestamp,
...,
PRIMARY KEY (system_serial_number,device_id,time_stamp)
);
我认为第一种方法可以防止我遇到列限制,但每次查询时都需要输入设备ID和序列号。第二种方法的列效率较低(根据我的理解),它只允许我按序列进行搜索。它们中的任何一个都不允许我只通过序列/时间戳进行搜索,这实际上是我要做的最常见的搜索,但它的唯一性不足以成为主键

我能够让查询正常工作的唯一方法是使用第一个带复合键的查询,然后为序列号添加一个二级索引,这样我就可以按序列号/时间戳进行搜索,但我必须使用低效的
允许过滤


关于获得我需要的东西的最佳方法有什么建议吗?

最简单的答案是:

PRIMARY KEY (system_serial_number, time_stamp, device_id)
  • system\u serial\u number
    将是标识哪些副本(节点)将包含数据的分区键。单个序列号的所有数据都需要放在同一个分区中。为了有效访问,所有查询都需要指定序列号。如果分区大小是一个问题,那么如果用例允许,可能会有进一步细分的方法

  • time\u stamp
    将是用于对分区内的行进行排序的集群键。也就是说,同一序列号的所有逻辑行都将按时间戳排序,而与设备无关。不是分区键一部分的第一个PK列确定排序顺序

  • device\u id
    是一个额外的PK列,用于区分逻辑行,但无助于排序或执行其他范围扫描

由于您提到每个设备将生成数千个时间戳,并且每个序列号将有许多设备,因此如果采用上述方法,您可能还需要关注分区的大小。一种常见的方法是在多个分区中为单个序列号断开数据,但这会使查询数据更高效或更麻烦,具体取决于您决定如何细分数据

您必须利用一些想象力和特定用例的知识来决定正确的分区布局。在我脑海中,我能想到一些想法:

  • 主键((系统序列号、设备哈希模数)、时间戳、设备id)

    • 想法:散列你的设备ID并应用一个模数将数据分割成固定数量的“桶”
    • 优点:使用均匀散列分布,可以在已知数量的节点上均匀分布数据
    • 缺点:跨“所有设备”查询给定序列号需要进行N次查询,根据为模运算选择的编号,每个“存储桶”一次查询
    • 缺点:如果初始选择对于最终数据大小来说太小,则可能需要调整bucketing方案(并迁移数据)
  • 主键((系统序列号、粗略时间戳)、时间戳、设备id)

    • 想法:随着时间的推移将数据分割成不同的分区,大小取决于分区时间戳(年?年+月?、年+日?)的粗糙程度。应根据给定时间段内预期的唯一记录数作出决定
    • 优点:假设集群配置了随机分区器,随着时间的推移,数据将均匀分布在集群周围
    • 缺点:在一段时间内查询记录可能需要对不同的分区进行单独的查询,这使得程序逻辑更加复杂。如果分区时间戳不够粗糙,或者要搜索的时间戳范围太宽,那么性能将受到影响
您可能还有其他选择,但这取决于您对当前用例的理解程度(以及您对数据集未来行为的预测程度)