Cassandra 需要关于适当的主键结构的建议
我有很多时间序列数据要存储在Cassandra数据库中。由于我只能对主键中的字段执行Cassandra 需要关于适当的主键结构的建议,cassandra,database,nosql,Cassandra,Database,Nosql,我有很多时间序列数据要存储在Cassandra数据库中。由于我只能对主键中的字段执行WHERE子句,因此我需要一些关于如何根据我需要查询它的方式进行布局的建议 我的数据采用以下格式: SYSTEM_SERIAL_NUMBER,DEVICE_ID,TIMESTAMP,...OTHER COLUMNS 每个序列号都有多个设备,每个设备都有数千个时间戳,因此我唯一标识每组数据的主键必须包括所有三个 基本上,我将对这些数据执行两种类型的查询 从表中选择*,其中系统序列号为'X',设备id为'X',时间
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
将是用于对分区内的行进行排序的集群键。也就是说,同一序列号的所有逻辑行都将按时间戳排序,而与设备无关。不是分区键一部分的第一个PK列确定排序顺序time\u stamp
是一个额外的PK列,用于区分逻辑行,但无助于排序或执行其他范围扫描device\u id
主键((系统序列号、设备哈希模数)、时间戳、设备id)
- 想法:散列你的设备ID并应用一个模数将数据分割成固定数量的“桶”
- 优点:使用均匀散列分布,可以在已知数量的节点上均匀分布数据
- 缺点:跨“所有设备”查询给定序列号需要进行N次查询,根据为模运算选择的编号,每个“存储桶”一次查询
- 缺点:如果初始选择对于最终数据大小来说太小,则可能需要调整bucketing方案(并迁移数据)
主键((系统序列号、粗略时间戳)、时间戳、设备id)
- 想法:随着时间的推移将数据分割成不同的分区,大小取决于分区时间戳(年?年+月?、年+日?)的粗糙程度。应根据给定时间段内预期的唯一记录数作出决定
- 优点:假设集群配置了随机分区器,随着时间的推移,数据将均匀分布在集群周围
- 缺点:在一段时间内查询记录可能需要对不同的分区进行单独的查询,这使得程序逻辑更加复杂。如果分区时间戳不够粗糙,或者要搜索的时间戳范围太宽,那么性能将受到影响