我们想通过 SparkSQL 从Cassandra DB查询数据。问题在于数据以 UDT 的形式存储在cassandra中。 UDT的结构是深层嵌套的,并且包含可变长度的数组,因此很难将数据分解为平面结构。 我找不到任何有效的示例,如何通过SparkSQL查询此类UDT,尤其是根据UDT值过滤结果。
或者,您是否可以建议其他ETL管道(查询引擎,存储引擎等),它更适合我们的用例?
我们的ETL管道:
Kafka(重复事件)-> Spark流-> Cassandra(重复数据删除以仅存储最新事件) <-Spark SQL <-分析平台(UI)
到目前为止我们尝试过的解决方案:
1)Kafka-> Spark-> 镶木地板 <-Apache Drill
一切正常,我们可以查询和过滤数组以及嵌套的数据结构。
问题:无法重复数据删除(使用最新事件重写镶木地板文件)
2)Kafka-> Spark-> Cassandra <-Presto
解决了重复数据删除问题1)。
问题:Presto不支持UDT类型(presto doc,presto issue)
我们的主要要求是:
感谢您的任何建议
答案 0 :(得分:1)
您可以只使用点语法对嵌套元素执行查询。例如,如果我具有以下CQL定义:
cqlsh> use test;
cqlsh:test> create type t1 (id int, t text);
cqlsh:test> create type t2 (id int, t1 frozen<t1>);
cqlsh:test> create table nudt (id int primary key, t2 frozen<t2>);
cqlsh:test> insert into nudt (id, t2) values (1, {id: 1, t1: {id: 1, t: 't1'}});
cqlsh:test> insert into nudt (id, t2) values (2, {id: 2, t1: {id: 2, t: 't2'}});
cqlsh:test> SELECT * from nudt;
id | t2
----+-------------------------------
1 | {id: 1, t1: {id: 1, t: 't1'}}
2 | {id: 2, t1: {id: 2, t: 't2'}}
(2 rows)
然后我可以按以下方式加载该数据:
scala> val data = spark.read.format("org.apache.spark.sql.cassandra").
options(Map( "table" -> "nudt", "keyspace" -> "test")).load()
data: org.apache.spark.sql.DataFrame = [id: int, t2: struct<id: int, t1: struct<id: int, t: string>>]
scala> data.cache
res0: data.type = [id: int, t2: struct<id: int, t1: struct<id: int, t: string>>]
scala> data.show
+---+----------+
| id| t2|
+---+----------+
| 1|[1,[1,t1]]|
| 2|[2,[2,t2]]|
+---+----------+
然后查询数据以仅选择UDT中字段的特定值:
scala> val res = spark.sql("select * from test.nudt where t2.t1.t = 't1'")
res: org.apache.spark.sql.DataFrame = [id: int, t2: struct<id: int, t1: struct<id: int, t: string>>]
scala> res.show
+---+----------+
| id| t2|
+---+----------+
| 1|[1,[1,t1]]|
+---+----------+
您可以使用spark.sql
或相应的.filter
函数-取决于您的编程风格。该技术适用于来自不同来源(例如JSON等)的任何结构类型数据。
但是要考虑到,您不会像通过分区键/集群列进行查询时那样从Cassandra连接器获得优化