我们使用Cassandra作为我们车队管理解决方案的数据历史记录.我们在卡桑德拉(Cassandra)有一张桌子,用于存储车辆行驶的详细信息.表结构如下
CREATE TABLE journeydetails( bucketid text, vehicleid text, starttime timestamp, stoptime timestamp, travelduration bigint, PRIMARY KEY (bucketid,vehicleid,starttime,travelduration) );
哪里:
bucketid: - 分区键,它是月份和年份的组合
vehicleid:车辆的唯一身份证
starttime: - 旅程的开始时间
结束时间: - 旅程的结束时间
travelduration: - 旅行持续时间,以毫秒为单位
我们想运行以下查询 - 获取车辆的所有行程 - 2015-12-1和2015-12-3之间的1234567,其行程持续时间大于30分钟
当我运行此查询时:
select * from journeydetails where bucketid in('2015-12') and vehicleid in('1234567') and starttime > '2015-12-1 00:00:00' and starttime < '2015-12-3 23:59:59' and travelduration > 1800000;
我得到这个结果:
InvalidRequest: code=2200 [Invalid query] message="Clustering column "travelduration" cannot be restricted (preceding column "starttime" is restricted by a non-EQ relation)
有没有人建议如何解决这个问题?
select * from journeydetails where bucketid in('2015-12') and vehicleid in('1234567') and starttime > '2015-12-1 00:00:00' and starttime < '2015-12-3 23:59:59' and travelduration > 1800000;
那不行.原因可以追溯到Cassandra如何在磁盘上存储数据.Cassandra的想法是,使用精确密钥返回单行或从磁盘返回连续范围的行非常有效.
你行被分割bucketid
,然后排序在磁盘上vehicleid
,starttime
和travelduration
.因为您已经在执行范围查询(非EQ关系)starttime
,所以不能限制后面的密钥.这是因为travelduration
限制可能会使您的范围条件中的某些行失去资格.这将导致低效,不连续的读取.Cassandra旨在保护您免于编写可能具有不可预测性能的查询(例如此类).
以下是两种选择:
1-如果您可以限制所有关键列travelduration
(使用等于关系),那么您可以应用大于条件:
select * from journeydetails where bucketid='2015-12' and vehicleid='1234567' and starttime='2015-12-1 00:00:00' and travelduration > 1800000;
当然,限制精确starttime
可能不是非常有用.
2-另一种方法是travelduration
完全省略,然后你的原始查询就可以了.
select * from journeydetails where bucketid='2015-12' and vehicleid='1234567' and starttime > '2015-12-1 00:00:00' and starttime < '2015-12-3 23:59:59';
不幸的是,Cassandra没有提供很大程度的查询灵活性.很多人使用像Spark这样的解决方案(和Cassandra一起)成功实现了这种级别的报告.
只是旁注,但IN
除非必须,否则不要使用.查询与IN
使用二级索引类似,因为Cassandra必须与多个节点通信以满足您的查询.用一个项目调用它可能不是太大的交易.但是IN
,在深入Cassandra之前,你应该真正打破那些旧的RDBMS习惯之一.