[英]In Scala, What is correct way to filter Spark Cassandra RDD by a List[String]?
我有一個字符串格式的 id 列表,這個列表大約有 20,000 個 id 長:
var timelineIds = source.map(a => a.timelineid);
timelineIds = timelineIds.distinct.cache; // disticnt list we need this for later
var timelineIdsString = timelineIds.map(a => a.asInstanceOf[String]).collect.toList;
當我對我的 cassandra 表之一使用此列表時,它工作得很好,無論timelineIdsString 的大小:
var timelineHistorySource = sc.cassandraTable[Timeline]("acd", "timeline_history_bytimelineid")
.select("ownerid", "userid", "timelineid", "timelinetype", "starttime", "endtime", "attributes", "states")
if (constrain)
timelineHistorySource = timelineHistorySource.where("timelineid IN ?", timelineIdsString)
當我對我的另一個表執行此操作時,當我在列表中有超過 1000 個 id 時,它永遠不會完成:
var dispositionSource = sc.cassandraTable[DispositionSource]("acd","dispositions_bytimelineid")
.select("ownerid","dispositionid","month","timelineid","createddate","createduserid")
if(constrain)
dispositionSource = dispositionSource.where("timelineid IN ?", timelineIdsString);
兩個 cassandra 表都將鍵作為時間線,所以我知道它是正確的。 只要timelineids 是一個小列表,此代碼就可以正常工作。
有沒有更好的方法從 cassandra RDD 過濾? 是否是導致它窒息的 IN 子句的大小?
您可以嘗試將 ID 列表保留為 dataframe、 timelineIds
和基於時間timelineid
的內部連接表。 然后從生成的 df 中刪除不必要的列 ( timelineIds.timelineid
)。
與其在 Spark 級別執行連接,不如使用 Cassandra 本身執行連接 - 在這種情況下,您將從 Cassandra 僅讀取必要的數據(假設連接鍵是分區或主鍵)。 對於 RDD,這可以通過.joinWithCassandraTable
function ( doc ) 來完成:
import com.datastax.spark.connector._
val toJoin = sc.parallelize(1 until 5).map(x => Tuple1(x.toInt))
val joined = toJoin.joinWithCassandraTable("test", "jtest1")
.on(SomeColumns("pk"))
scala> joined.toDebugString
res21: String =
(8) CassandraJoinRDD[150] at RDD at CassandraRDD.scala:18 []
| ParallelCollectionRDD[147] at parallelize at <console>:33 []
對於 Dataframes,它被稱為直接連接,自 SCC 2.5 起可用(請參閱公告)-您需要傳遞一些配置以啟用它,請參閱文檔:
import spark.implicits._
import org.apache.spark.sql.cassandra._
val cassdata = spark.read.cassandraFormat("jtest1", "test").load
val toJoin = spark.range(1, 5).select($"id".cast("int").as("id"))
val joined = toJoin.join(cassdata, cassdata("pk") === toJoin("id"))
scala> joined.explain
== Physical Plan ==
Cassandra Direct Join [pk = id#2] test.jtest1 - Reading (pk, c1, c2, v) Pushed {}
+- *(1) Project [cast(id#0L as int) AS id#2]
+- *(1) Range (1, 5, step=1, splits=8)
我有一篇關於與 Cassandra 連接的相當長而詳細的博客文章- 查看更多詳細信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.