如何创建多个Spark任务来查询Cassandra分区

时间:2019-02-07 08:45:49

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

我有一个使用Spark(带有Spark Job Server)的应用程序,该应用程序使用Cassandra存储。我当前的设置是在client下运行的master=local[*]模式。因此,只有一个Spark执行程序,它也是使用机器所有8个内核的驱动程序进程。我有一个在同一台计算机上运行的Cassandra实例。

Cassandra表的主键的格式为((datasource_id,date),clustering_col_1 ... clustering_col_n),其中date是单日,格式为“ 2019-02-07”,并且是复合分区键的一部分

在我的Spark应用程序中,我正在运行如下查询:

df.filter(col("date").isin(days: _*))

在Spark物理计划中,我注意到这些过滤器以及“ datasource_id”分区键的过滤器均被推送到Cassandra CQL查询中。

对于我们最大的数据源,我知道分区的大小约为30MB。因此,我在Spark Job Server配置中具有以下设置:

spark.cassandra.input.split.size_in_mb = 1

但是,我注意到在Cassandra加载步骤中没有并行化。尽管有多个大于1MB的Cassandra分区,但是没有创建其他的spark分区。只有一个任务可以在单个核心上执行所有查询,因此需要大约20秒钟的时间来加载对应于大约100万行的1个月日期范围内的数据。

我尝试了以下替代方法:

  df union days.foldLeft(df)((df: DataFrame, day: String) => {
    df.filter(col("date").equalTo(day))
  })

这确实为cassandra中的每个“ day”分区创建了一个火花分区(或任务)。但是,对于cassandra分区的大小较小的较小数据源,就创建过多的任务以及由于它们的协调而造成的开销而言,该方法被证明是相当昂贵的。对于这些数据源,将许多Cassandra分区集中到一个spark分区中完全可以。因此,为什么我认为使用spark.cassandra.input.split.size_in_mb配置对于处理小型和大型数据源都是有用的。

我的理解错误吗?为了使此配置生效,我还缺少其他东西吗?

P.S。我还阅读了有关使用joinWithCassandraTable的答案。但是,我们的代码依赖于使用DataFrame。同样,从CassandraRDD转换为DataFrame对我们来说也不可行,因为我们的架构是动态的,无法使用案例类进行指定。

0 个答案:

没有答案