我有很多时间序列数据,我想存储在Cassandra数据库中。由于我只能对主键中的字段执行WHERE
子句,因此我需要一些建议,说明如何根据我查询它的方式来解决这个问题。
我的数据采用以下格式:
SYSTEM_SERIAL_NUMBER,DEVICE_ID,TIMESTAMP,...OTHER COLUMNS
每个序列号都有多个设备,每个设备都有数千个时间戳,因此唯一标识每组数据的主键必须包含所有三个。
我将对此数据进行基本上两种类型的查询。
SELECT * FROM TABLE WHERE system_serial_number = 'X' and device_id = 'x' and timestamp
(在范围内)
或
SELECT * FROM TABLE WHERE system_serial_number = 'X' and 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和Serial。第二个是列效率较低(基于我的理解),它允许我只通过序列搜索。他们中的任何一个都不允许我通过串行/时间戳进行搜索,这实际上是我将要进行的最常见的搜索,但并不是唯一足以成为主键的。
我能够让查询工作的唯一方法是使用带有复合键的第一个,然后为序列号添加二级索引,然后允许我按序列搜索/时间戳,但我必须使用效率低下的ALLOW FILTERING
。
有关获得我需要的最佳方式的任何建议吗?
答案 0 :(得分:1)
最简单的答案是:
PRIMARY KEY (system_serial_number, time_stamp, device_id)
system_serial_number
将是分区密钥,用于标识哪些副本(节点)将包含数据。单个序列号的所有数据都需要适合同一个分区。为了有效访问,将需要所有查询来指定序列号。如果分区大小是一个问题,如果用例允许,可能有进一步细分的方法。
time_stamp
将是用于对分区内的行进行排序的群集密钥。也就是说,无论设备如何,相同序列号的所有逻辑行都将按时间戳排序。 不是分区键的第一个PK列确定排序顺序。
device_id
是用于区分逻辑行的附加PK列,但不会帮助您排序或执行其他范围扫描。
由于您提到每个设备都会生成数千个时间戳,并且每个序列号都有许多设备,因此如果采用上述方法,您可能还需要关注分区的大小。一种常见的方法是在多个分区中中断单个序列号的数据,但这可以使查询数据更高效或更麻烦,具体取决于您决定细分数据的方式。
您必须使用一些想象力和特定用例的知识来决定正确的分区布局。我能想到一些想法:
PRIMARY KEY ((system_serial_number, device_hash_modulus), time_stamp, device_id)
PRIMARY KEY ((system_serial_number, coarse_time_stamp), time_stamp, device_id)
您可能还有其他选择,但这取决于您对当前用例的理解程度(以及您预测数据集未来行为的程度)。