这是我的spark应用程序的一部分。第一部分是我在过去1小时内获得所有文章的部分,代码的第二部分抓取所有这些文章的评论。第三部分将评论添加到文章中。
问题是articles.map(lambda x:(x.id,x.id)).join(axes)
部分太慢,大约需要1分钟。我想把它提高到10秒甚至更短但不知道怎么做?谢谢你的回复。
articles = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table="articles", keyspace=source).load() \
.map(lambda x:x).filter(lambda x:x.created_at!=None).filter(lambda x:x.created_at>=datetime.now()-timedelta(hours=1) and x.created_at<=datetime.now()-timedelta(hours=0)).cache()
axes = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table="axes", keyspace=source).load().map(lambda x:(x.article,x))
speed_rdd = articles.map(lambda x:(x.id,x.id)).join(axes)
修改
这是我的新代码,我根据您的建议进行了更改。它现在已经是以前的2倍,所以谢谢你;)。我想用轴部分的代码的最后一部分进行另一项改进,这仍然太慢,需要38秒才能获得3000万个数据:
range_expr = col("created_at").between(
datetime.now()-timedelta(hours=timespan),
datetime.now()-timedelta(hours=time_delta(timespan))
)
article_ids = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table="article_by_created_at", keyspace=source).load().where(range_expr).select('article','created_at').persist()
axes = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table="axes", keyspace=source).load()
我在这里尝试了这个(它应该替换我的代码的最后一个轴部分),这也是我想要的解决方案,但它似乎没有正常工作:
in_expr = col("article").isin(article_ids.collect())
axes = sqlContext.read.format("org.apache.spark.sql.cassandra").options(table="axes", keyspace=source).load().where(in_expr)
我总是收到此错误消息:
in_expr = col("article").isin(article_ids.collect())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Column' object is not callable
感谢您的帮助。
答案 0 :(得分:3)
1)只要在Cassandra中进行过滤(使用主键进行过滤或二级索引),Spark-Cassandra连接器就会自动检测谓词下推:https://github.com/datastax/spark-cassandra-connector/blob/master/doc/14_data_frames.md#pushing-down-clauses-to-cassandra
2)对于更有效的连接,您可以调用方法repartitionByCassandraReplica
。不幸的是,这种方法可能不适用于PySpark,仅适用于Scala / Java API。请阅读此处的文档:https://github.com/datastax/spark-cassandra-connector/blob/master/doc/2_loading.md#performing-efficient-joins-with-cassandra-tables-since-12
3)另一个提示是尝试调试并了解连接器如何创建Spark分区。文档中提到了一些示例和警告:https://github.com/datastax/spark-cassandra-connector/blob/master/doc/16_partitioning.md
答案 1 :(得分:2)
作为mentioned before,如果您想获得合理的效果,请不要将您的数据转换为RDD
。它不仅不会使谓词下推等优化变得不可能,而且还会带来将数据从JVM迁移到Python的巨大开销。
相反,您应该以类似于此的方式使用SQL表达式/ DataFrame
API:
from pyspark.sql.functions import col, expr, current_timestamp
range_expr = col("created_at").between(
current_timestamp() - expr("INTERVAL 1 HOUR"),
current_timestamp())
articles = (sqlContext.read.format("org.apache.spark.sql.cassandra")
.options(...).load()
.where(col("created_at").isNotNull()) # This is not really required
.where(range_expr))
也应该像以前一样使用标准的Python实用程序来制定谓词表达式:
import datetime
range_expr = col("created_at").between(
datetime.datetime.now() - datetime.timedelta(hours=1),
datetime.datetime.now()
)
应该执行后续join
而不会将数据移出数据框:
axes = (sqlContext.read.format("org.apache.spark.sql.cassandra")
.options(...)
.load())
articles.join(axes, ["id"])