Cassandra 错误 - 无法限制聚类列(前面的列受非 EQ 关系限制)

Cassandra Error - Clustering column cannot be restricted (preceding column is restricted by a non-EQ relation)

我们使用 Cassandra 作为车队管理解决方案的历史数据。我们在 Cassandra 中有一个 table ,它存储车辆行驶的详细信息。 table结构如下

CREATE TABLE  journeydetails(
bucketid text,
vehicleid text,
starttime timestamp,
stoptime timestamp,
travelduration bigint,
PRIMARY KEY (bucketid,vehicleid,starttime,travelduration)
);

其中:

  1. bucketid :- 分区键是月和年的组合
  2. vehicleid : - 车辆的唯一 ID
  3. 开始时间:- 旅程的开始时间
  4. 结束时间:- 旅程结束时间
  5. travelduration:- 以毫秒为单位的旅行持续时间

我们想运行以下查询 - 获取车辆的所有行程 - 1234567 在 2015-12-1 和 2015-12-3 之间,行程时间大于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 分区,然后在磁盘上按 vehicleidstarttimetravelduration 排序。因为您已经在 starttime 上执行范围查询(非 EQ 关系),所以您无法限制后面的键。这是因为 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(与 Ca​​ssandra 一起)这样的解决方案来实现这种级别的报告。

这只是一个旁注,但除非万不得已,否则不要使用 IN。使用 IN 查询类似于使用二级索引,因为 Cassandra 必须与多个节点通信才能满足您的查询。用单个项目调用它可能没什么大不了的。但是 IN 是 RDBMS 的旧习惯之一,在深入了解 Cassandra 之前,您真的应该改掉这些习惯。

我运行遇到同样的问题。您可以简单地将索引添加到所需的列,而不是使用聚簇键和主键。有了这个,您就可以摆脱这些陷阱,并且可以在查询中使用您想要的任何列。

原来你可以在查询结束时使用 'allow filtering'