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)
);
其中:
- bucketid :- 分区键是月和年的组合
- vehicleid : - 车辆的唯一 ID
- 开始时间:- 旅程的开始时间
- 结束时间:- 旅程结束时间
- 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
分区,然后在磁盘上按 vehicleid
、starttime
和 travelduration
排序。因为您已经在 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(与 Cassandra 一起)这样的解决方案来实现这种级别的报告。
这只是一个旁注,但除非万不得已,否则不要使用 IN
。使用 IN
查询类似于使用二级索引,因为 Cassandra 必须与多个节点通信才能满足您的查询。用单个项目调用它可能没什么大不了的。但是 IN
是 RDBMS 的旧习惯之一,在深入了解 Cassandra 之前,您真的应该改掉这些习惯。
我运行遇到同样的问题。您可以简单地将索引添加到所需的列,而不是使用聚簇键和主键。有了这个,您就可以摆脱这些陷阱,并且可以在查询中使用您想要的任何列。
原来你可以在查询结束时使用 'allow filtering'
我们使用 Cassandra 作为车队管理解决方案的历史数据。我们在 Cassandra 中有一个 table ,它存储车辆行驶的详细信息。 table结构如下
CREATE TABLE journeydetails(
bucketid text,
vehicleid text,
starttime timestamp,
stoptime timestamp,
travelduration bigint,
PRIMARY KEY (bucketid,vehicleid,starttime,travelduration)
);
其中:
- bucketid :- 分区键是月和年的组合
- vehicleid : - 车辆的唯一 ID
- 开始时间:- 旅程的开始时间
- 结束时间:- 旅程结束时间
- 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
分区,然后在磁盘上按 vehicleid
、starttime
和 travelduration
排序。因为您已经在 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(与 Cassandra 一起)这样的解决方案来实现这种级别的报告。
这只是一个旁注,但除非万不得已,否则不要使用 IN
。使用 IN
查询类似于使用二级索引,因为 Cassandra 必须与多个节点通信才能满足您的查询。用单个项目调用它可能没什么大不了的。但是 IN
是 RDBMS 的旧习惯之一,在深入了解 Cassandra 之前,您真的应该改掉这些习惯。
我运行遇到同样的问题。您可以简单地将索引添加到所需的列,而不是使用聚簇键和主键。有了这个,您就可以摆脱这些陷阱,并且可以在查询中使用您想要的任何列。
原来你可以在查询结束时使用 'allow filtering'