使用RDD从大型C *表中提取少量分区时,我们可以使用:
val rdd = … // rdd including partition data
val data = rdd.repartitionByCassandraReplica(keyspace, tableName)
.joinWithCassandraTable(keyspace, tableName)
我们是否有使用DataFrames同样有效的方法?
更新(2017年4月26日):
更具体一点,我准备了一个例子。
我在Cassandra有两张桌子:
CREATE TABLE ids (
id text,
registered timestamp,
PRIMARY KEY (id)
)
CREATE TABLE cpu_utils (
id text,
date text,
time timestamp,
cpu_util int,
PRIMARY KEY (( id, date ), time)
)
第一个包含有效ID列表和第二个cpu利用率数据。我希望有效地获得表 ids 中每个 id 一天的平均cpu利用率,比如说“2017-04-25”。
我所知道的RDD最有效的方法如下:
val sc: SparkContext = ...
val date = "2017-04-25"
val partitions = sc.cassandraTable(keyspace, "ids")
.select("id").map(r => (r.getString("id"), date))
val data = partitions.repartitionByCassandraReplica(keyspace, "cpu_utils")
.joinWithCassandraTable(keyspace, "cpu_utils")
.select("id", "cpu_util").values
.map(r => (r.getString("id"), (r.getDouble("cpu_util"), 1)))
// aggrData in form: (id, (avg(cpu_util), count))
// example row: ("718be4d5-11ad-4849-8aab-aa563c9c290e",(6,723))
val aggrData = data.reduceByKey((a, b) => (
1d * (a._1 * a._2 + b._1 * b._2) / (a._2 + b._2),
a._2 + b._2))
aggrData.foreach(println)
此方法需要大约5秒钟才能完成(在我的本地计算机上安装Spark,在某些远程服务器上安装Cassandra)。使用它,我在表cpu_utils中的不到1%的分区上执行操作。
使用Dataframes这是我目前使用的方法:
val sqlContext = new SQLContext(sc)
import sqlContext.implicits._
val date = "2017-04-25"
val partitions = sqlContext.read.format("org.apache.spark.sql.cassandra")
.options(Map("table" -> "ids", "keyspace" -> keyspace)).load()
.select($"id").withColumn("date", lit(date))
val data: DataFrame = sqlContext.read.format("org.apache.spark.sql.cassandra")
.options(Map("table" -> "cpu_utils", "keyspace" -> keyspace)).load()
.select($"id", $"cpu_util", $"date")
val dataFinal = partitions.join(data, partitions.col("id").equalTo(data.col("id")) and partitions.col("date").equalTo(data.col("date")))
.select(data.col("id"), data.col("cpu_util"))
.groupBy("id")
.agg(avg("cpu_util"), count("cpu_util"))
dataFinal.show()
然而,这种方法似乎将整个表cpu_utils加载到内存中,因为这里的执行时间相当长(差不多1分钟)。
我在问是否有更好的方法使用Dataframes,如果表现不如上面提到的RDD方法那么至少可以达到?
P.s。:我正在使用Spark 1.6.1。