【问题标题】:Error while running range query on multiple clustering columns using spark cassandra connector:使用 spark cassandra 连接器在多个集群列上运行范围查询时出错:
【发布时间】:2017-07-27 04:36:12
【问题描述】:

以下是 cassandra 表架构:

创建表 my_table ( 年文, 月文本, 日文, 小时整数, 最小整数, 秒整数, 主键((年、月、日)、时、分、秒))

如果我使用 cassandra cql 运行以下查询,它可以工作:

SELECT * FROM my_table WHERE year ='2017' and month ='01' and day ='16' and (hour,min,sec) > (1,15,0) LIMIT 200

但是,当我使用 spark-cassandra 连接器运行相同的查询时,它不起作用:

sparkSession.read().format("org.apache.spark.sql.cassandra").options(map).load()
                .where(year ='2017' and month ='01' and day ='16' and (hour,min,sec) >= (1,15,0)");

我在日志中收到以下异常:

> Exception in thread "main" org.apache.spark.sql.AnalysisException:
> cannot resolve '(struct(`hour`, `min`, `sec`) >= struct(1, 15, 0))'
> due to data type mismatch: differing types in '(struct(`hour`, `min`,
> `sec`) >= struct(1, 15, 0))'  and (struct<hour:int,min:int,sec:int>
> struct<col1:int,col2:int,col3:int>).; line 1 pos 96

Spark-cassandra-connector 版本:2.0.0-M3

Spark 版本:2.0.0

非常感谢任何帮助

【问题讨论】:

  • 你能像这样独立尝试吗and hour &gt;= 1 and min &gt;= 15 and sec &gt;=0,因为这对我的场景有用。
  • 这在 cassandra cql 中也不起作用,因为小时、分钟和秒都是集群键的一部分。要在任何列聚类键上运行范围,前一列应与相等条件一起使用。即在 min 列上运行“> =”,小时只能包含等于(=)操作条件,否则会发生以下异常:com.datastax.driver.core.exceptions.InvalidQueryException:PRIMARY KEY 列“min”不能被限制(前面“小时”列受非 EQ 关系限制)
  • @AkashSethi:奇怪的是它在 Spark 中运行,但它没有给出预期的结果。因为问题中发布的查询将返回 01:15:00 之后一天的所有行。但在输出中,每小时的行将在第 15 分钟后开始

标签: apache-spark cassandra spark-cassandra-connector


【解决方案1】:

很简单,CQL 与 Spark Sql 或 Catalyst 不兼容。您看到的是语法冲突。

这个 where 子句:

.where(year ='2017' and month ='01' and day ='16' and (hour,min,sec) >= (1,15,0)

不直接下推到Cassandra。相反,它正在转化为催化剂谓词。这就是你有问题的地方

Cataylst 看到了这个

(hour,min,sec) >= (1,15,0)

并尝试为他们制作类型

左边变成

struct<hour:int,min:int,sec:int>

右手边变成

struct<col1:int,col2:int,col3:int>

这些不是元组,而是显式类型的结构。它们不能直接比较,因此您的错误。在 DataFrame api 中,您只需定义一个具有正确类型的新 Struct 并对其进行文字说明,但我不确定如何在 SparkSQL 中表达它。

不管这个元组谓词不会下推到 Cassandra。您定义的小时、分钟、秒结构将对 Cassandra 隐藏,因为基础表不提供 Struct&lt;hour, min, sec&gt;,这意味着 Spark 认为它需要在从 Cassandra 提取数据后生成它。

您最好只使用带有AND 的单独子句,如 @AkashSethi

【讨论】:

  • 感谢@RussS 的回复。但是,带有 AND 的单独子句不会产生所需的结果。一种方法是我使用分区键在 Spark 中读取一整天的数据,然后使用 spark sql 对其进行过滤。但是如果我可以通过运行查询得到结果,那会更快
  • 您不能将 where 子句从 Spark SQL 推送到 Cassandra。您可以做到这一点的唯一方法是在 Cassandra RDD 上使用 where 方法。
猜你喜欢
  • 2016-07-21
  • 1970-01-01
  • 2015-08-16
  • 2017-01-13
  • 2015-08-24
  • 1970-01-01
  • 2019-06-18
  • 2019-11-28
  • 2020-10-04
相关资源
最近更新 更多