Cassandra帮助:支持使用组合键的任意一部分进行快速查询



我是Cassandra的新手,不清楚存储数据以满足查询需求的最佳方式。我希望能够根据其中一个键或两个键来搜索我的数据。为了说明,我将使用以下表格示例:

CREATE TABLE temperature (
weatherstation_id text,
event_time timestamp,
temperature text,
PRIMARY KEY (weatherstation_id,event_time)
);

这对于以下两种查询非常有效:

SELECT event_time,temperature FROM temperature WHERE weatherstation_id=’1234ABCD’;

因为它直接进入单个分区

SELECT temperature FROM temperature WHERE weatherstation_id=’1234ABCD’ AND event_time > ’2013-04-03 07:01:00′ AND event_time < ’2013-04-03 07:04:00′;

因为它仍然去到一个单独的分区,并从有序列表中获得一部分结果

然而,如果我想要这样的东西呢:

SELECT temperature FROM temperature WHERE event_time > ’2013-04-03 07:01:00′ AND event_time < ’2013-04-03 07:04:00′;

如果我的理解正确的话,这不是效率低下吗,因为它需要在每个分区上迭代吗?不仅如此,还需要采取措施使其按时间顺序恢复。

绕过这个问题的最佳设计是什么?

实际上您的查询:

SELECT temperature FROM temperature WHERE event_time > ’2013-04-03 07:01:00′ AND event_time < ’2013-04-03 07:04:00′;

将无法运行。Cassandra真的必须知道在哪个分区中必须查找您请求的数据,也就是说,您总是需要指定分区键。

为了有效地检索该查询的数据,您还需要围绕该查询对数据进行建模:

CREATE TABLE temperature_by_time (
granularity timestamp,
event_time timestamp,
weatherstation_id text,
temperature text,
PRIMARY KEY (granularity, event_time)    
);

在这里我添加了字段granularity。此字段允许您控制分区的宽度。一个好的经验法则是在每个分区中最多有大约10k-100k行。根据您写入此表的速度,您可以使用不同的方式进行操作。示例:


情况1

  • 您有10个传感器
  • 每个传感器每秒测量一次

在这种情况下,你将每秒写10个度量值,36k个度量值/小时。一个好的粒度值类似于yyyy-mm-dd HH:00:00,也就是说,您可以逐小时对数据进行分区:

INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:00:00', '2017-01-11 10:05:01', ...);
INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:00:00', '2017-01-11 10:19:15', ...);
INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:00:00', '2017-01-11 10:39:35', ...);
INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:00:00', '2017-01-11 10:59:49', ...);
SELECT * FROM temperature_by_time WHERE granularity='2017-01-11 10:00:00';
SELECT * FROM temperature_by_time WHERE granularity='2017-01-11 10:00:00' AND event_time >= '2017-01-1 10:30:00' AND event_time < '2017-01-1 11:00:00';

也就是说,您将event_time"截断"为整数小时,并且只能获得每小时小时的记录。


情况2

  • 您有100个传感器
  • 每个传感器每秒测量一次

在这种情况下,您将每秒写入100个度量值,即360k个度量值/小时。好的粒度值类似于yyyy-mm-dd HH:00:00yyyy-mm-dd HH:15:00yyyy-mm-dd HH:30:00yyyy-mm-dd HH:45:00,也就是说,您可以在四分之一小时的基础上对数据进行分区:

INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:00:00', '2017-01-11 10:05:01', ...);
INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:15:00', '2017-01-11 10:19:15', ...);
INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:30:00', '2017-01-11 10:39:35', ...);
INSERT INTO temperature_by_time (granularity, event_time, ..) VALUES ('2017-01-11 10:45:00', '2017-01-11 10:59:49', ...);
SELECT * FROM temperature_by_time WHERE granularity='2017-01-11 10:00:00';
SELECT * FROM temperature_by_time WHERE granularity='2017-01-11 10:00:00' AND event_time >= '2017-01-1 10:30:00' AND event_time < '2017-01-1 10:33:00';

也就是说,您将event_time"截断"为一刻钟,并且只能获得一刻钟的记录。


情况3

你已经知道如何继续。。。

PRIMARY KEY ((day_of_year), event_time, weatherstation_id)将使您能够在一天内完成一定范围的时间。若周期跨越多天,则按day_of_year进行查询,并将它们合并到应用程序中。

然后需要采用按时间顺序将其取回

不,在您的示例中不会,因为它会返回按时间排序的行,一次返回一个分区。但使用我上面列出的主键,它会按时间列出它们,而与weatherstation_id无关。

最新更新