我是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:00
、yyyy-mm-dd HH:15:00
、yyyy-mm-dd HH:30:00
、yyyy-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无关。