我正在做时间序列数据建模,其中我有事件的开始日期和结束日期。我需要查询该数据模型,如下所示:
Select * from tablename where startdate>'2012-08-09' and enddate<'2012-09-09'
我在cql where 子句中提到了以下链接,但我无法做到这一点。有什么办法吗?我还可以更改数据模型或任何 cql 调整。我正在使用 Cassandra 2.1。
我正在做时间序列数据建模,其中我有事件的开始日期和结束日期。我需要查询该数据模型,如下所示:
Select * from tablename where startdate>'2012-08-09' and enddate<'2012-09-09'
我在cql where 子句中提到了以下链接,但我无法做到这一点。有什么办法吗?我还可以更改数据模型或任何 cql 调整。我正在使用 Cassandra 2.1。
我不得不在我以前的一个职位上解决类似的问题。这是您可以实现此目的的一种方式...
我需要对该数据模型进行查询,如下所示
Select * from tablename where startdate>'2012-08-09' and enddate<'2012-09-09'
:
有两个建模问题阻止此查询工作。首先,要运行范围查询,首先需要使用分区键限制查询。对于时间序列数据,最好的想法是创建一个称为时间桶的东西。对于这个例子,我将按月对数据进行分区,分区键名为monthbucket
.
另一个问题是您只能对单个列/键值运行范围查询。当您想同时按开始日期和结束日期进行查询时,这会成为问题。一种解决方案是将表中的每一行存储两次,并创建一个额外的集群键来保存该行是开始行还是结束行的值。我就叫这个专栏beginend
。
鉴于这些注释,我将创建一个如下所示的表:
CREATE TABLE events (
monthBucket TEXT,
eventDate TIMESTAMP,
beginEnd TEXT,
eventid UUID,
eventName TEXT,
PRIMARY KEY (monthBucket, eventDate, beginEnd, eventid))
WITH CLUSTERING ORDER BY (eventDate DESC, beginEnd ASC, eventid ASC);
eventDate
以 DESCending 顺序进行聚类。eventid
在这种情况下)。在插入一些行之后,让我们通过 2015 年 9 月的分区键查询:
aploetz@cqlsh:stackoverflow> SELECT * FROM events WHERE monthbucket='201509';
monthbucket | eventdate | beginend | eventid | eventname
-------------+--------------------------+----------+--------------------------------------+------------------------
201509 | 2015-09-25 23:59:59+0000 | E | a223ad16-2afd-4213-bee3-08a2c4dd63e6 | Hobbit Day
201509 | 2015-09-25 00:00:00+0000 | B | a223ad16-2afd-4213-bee3-08a2c4dd63e6 | Hobbit Day
201509 | 2015-09-24 23:59:59+0000 | E | 9cd6a265-6c60-4537-9ea9-b57e7c152db9 | Cassandra Summit
201509 | 2015-09-22 00:00:00+0000 | B | 9cd6a265-6c60-4537-9ea9-b57e7c152db9 | Cassandra Summit
201509 | 2015-09-19 23:59:59+0000 | E | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
201509 | 2015-09-19 00:00:00+0000 | B | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
(6 rows)
与您的示例类似,假设我要查询 9 月 18 日至 9 月 24 日之间的事件:
aploetz@cqlsh:stackoverflow> SELECT * FROM events WHERE monthbucket='201509' AND eventdate > '2015-09-18' AND eventdate < '2015-09-24';
monthbucket | eventdate | beginend | eventid | eventname
-------------+--------------------------+----------+--------------------------------------+------------------------
201509 | 2015-09-22 00:00:00+0000 | B | 9cd6a265-6c60-4537-9ea9-b57e7c152db9 | Cassandra Summit
201509 | 2015-09-19 23:59:59+0000 | E | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
201509 | 2015-09-19 00:00:00+0000 | B | b9fe9668-cef2-464e-beb4-d4f985ef9c47 | Talk Like a Pirate Day
(3 rows)
如您所见,我应该得到三行:“Talk Like A Pirate Day”的开始行和结束行以及 2015 Cassandra 峰会的开始行。
与所有数据建模方法一样,需要权衡取舍。在这种情况下,要对两个日期的查询进行建模,权衡是您必须复制行。当然,为了能够进行范围查询,您必须确定一个良好的分区键 ( monthbucket
) 以提供相关数据和所需的查询灵活性。无论如何,试一试,看看你是否可以让它适用于你的用例。
编辑以回答问题:
如果我想查找 2015 年 11 月 25 日至 2016 年 11 月 25 日之间的所有事件。这怎么可能?
这就是您需要为您的应用程序找出最佳时间段的地方。想想你最常见的查询,并以此为模型。现在您不想在单行(存储桶)中存储太多,因为这会破坏您的数据分布。因此,请尝试在查询灵活性和数据分布之间找到一个快乐的中介。
在这种特殊情况下,monthBucket
您必须为每个月执行一次查询。我为其设计此解决方案的应用程序从未同时查看一整年的事件。如果这是您需要支持的查询模式,那么您需要使您的时间桶更大一点。
有没有办法只从结果集中删除这个重复的行?
没有。需要在应用程序级别处理/忽略重复项。Cassandra CQL 确实有一个 DISTINCT 关键字,但它只对分区键起作用。
这种类型的合并可以在 Cassandra 级别完成吗?
不,Cassandra 没有办法将表连接在一起。应用程序端连接是可能的,但性能不佳,并且在技术上是一种反模式。
在应用程序端处理数据(无论是加入还是过滤)通常不是一个好主意。但关键是适度。如果您查询 20 个事件并且必须忽略其中一些事件的欺骗,这没什么大不了的。但是查询 20,000,000 个事件并在该数量上应用应用程序端进程根本无法很好地扩展。同样,您必须在此处查看可用选项,并决定哪些选项适用于您的应用程序。