Showing posts with label spark-cassandra-connector. Show all posts
Showing posts with label spark-cassandra-connector. Show all posts

Sunday, April 8, 2018

How to pushdown limit predicate for Cassandra when you use dataframes?

Leave a Comment

I have large Cassandra table. I want to load only 50 rows from Cassandra. Following code

val ds = sparkSession.read       .format("org.apache.spark.sql.cassandra")       .options(Map("table" -> s"$Aggregates", "keyspace" -> s"$KeySpace"))       .load()       .where(col("aggregate_type") === "DAY")       .where(col("start_time") <= "2018-03-28")       .limit(50).collect() 

Following code pushes both predicates from where methods, but not limit one. Is it true that whole data (1 million of records) being fetched? If not, why run time of this code and code without limit(50) roughly the same.

1 Answers

Answers 1

Unlike Spark Streaming, Spark itself is trying to preload as much data as it can, as fast as it can so to be able operate on it in parallel. So preloading is lazy, but greedy when it's triggered. There are cassandra-conector specific factors however:

  • Automatic predicate pushdown of valid "where" clauses.

  • According to this answer limit(...) is not translated to CQL's LIMIT, so then its behavior depends on how many fetching jobs are created after enough data is downloaded. Quote:

calling limit will allow Spark to skip reading some portions from the underlying DataSource. These would limit the amount of data read from Cassandra by canceling tasks from being executed.

Possible solutions:

  • DataFrame limits could be partially managed by limiting numPartitions and data exchange rate (concurrent.reads and other params). If you're okay with n ~ 50 "in most cases", you could also limit something like where(dayIndex < 50 * factor * num_records).

  • There is a way to set CQL LIMIT through SparkPartitionLimit, which is directly affecting every CQL request (see more) - keep in mind that requests are per-spark-partition. It's available in CassandraRdd extension class, so you would have to convert to RDD first.

The code would be something like:

filteredDataFrame.rdd.asInstanceOf[CassandraRDD].limit(n).take(n).collect() 

This would append LIMIT $N to every CQL-request. Unlike with DataFrame's limit, if you specify CassandraRDD limit several times (.limit(10).limit(20)) - only last one is going to be appended. Also, I used n instead of n / numPartitions + 1 as it (even if Spark and Cassandra partitions are one-to-one) might return less results per-partition (given that requests run in parallel - it shouldn't hurt performance too much). As a result, I had to add take(n) in order to cut <= numPartitions * n down to n.

Warning double-check that your where's are translatable to CQL (using explain()) - otherwise LIMIT would be applied before filtering.

P.S. You could also try to run CQL directly using sparkSession.sql(...) (like here) and compare results.

Read More

Tuesday, February 7, 2017

bulk insert into Cassandra UDT using spark

Leave a Comment

I am using spark to bulk insert Facebook data for analysis I have comment as a UDT in cassandra . the a table fbpost that has set of comments as a column Below is the schema

CREATE TYPE analytics.comment ( commentid text, commenttext varchar, username text, commentdatetime timestamp );  CREATE TABLE analytics.posts ( postid text, username text, comments set<frozen<comment>>, datetime timestamp, posttext varchar, PRIMARY KEY (datetime, username)  

from the spark job written in Java I am creating a JavaRDD(of type FBposts) which i need to save in the Cassandra table. I have pojos for both FBpost and Comments .

 javaFunctions(fbPostFromMysql).writerBuilder("analytics", "posts", fbPostWriter).saveToCassandra(); 

May be I am not doing the mapping for my Java comment pojo to UDTValue correctly which is why i am getting TypeConversionException below is the stacktrace

localhoatastax.spark.connector.types.TypeConversionException: Cannot convert object Comment [commentId=642528915901340_642701759217389, commenttext=Prix, username=Angel Nannousa, commentdatetime=2016-07-0  class com.prophecy.spark.cassandra.model.Comment to com.datastax.driver.core.UDTValue 

Here is the java code for rowwriter

public class FbPostRowWriter implements RowWriter<FbPost> { private static final long serialVersionUID = 1L; private static RowWriter<FbPost> writer = new FbPostRowWriter();  // Factory public static class FbPostRowWriterFactory implements RowWriterFactory<FbPost>, Serializable{     private static final long serialVersionUID = 1L;      @Override     public RowWriter<FbPost> rowWriter(TableDef tableDef, IndexedSeq<ColumnRef> arg1) {         return writer;     } }  @Override public Seq<String> columnNames() {           return scala.collection.JavaConversions.asScalaBuffer(FbPost.columns()).toList(); }  @Override public void readColumnValues(FbPost summary, Object[] buffer) {     buffer[0] = summary.getPostId();     buffer[1] = summary.getUsername();     buffer[3] = summary.getDatetime();     buffer[4] = summary.getPosttext();       buffer[2] = summary.getComments();     } } 

Please suggest How do I map set of Comment to be able to insert data in UDT column

0 Answers

Read More

Friday, April 1, 2016

Not able to change Authentication in spark-cassandra-connector

Leave a Comment

I am creating one Spark-Cassandra App (Spark 1.6.0 & spark-cassandra-connector 1.6.0-M1), in which i am asking multiple users to enter their Cassandra properties like Host, Username, Password, Keyspace, Table and others.

To change the above properties dynamically and create dataframe from Cassandra table, I Googled and found out some information

http://www.russellspitzer.com/2016/02/16/Multiple-Clusters-SparkSql-Cassandra/

https://github.com/datastax/spark-cassandra-connector/blob/master/doc/14_data_frames.md#setting-cluster-and-keyspace-level-options

val csc = new CassandraSQLContext(SparkConnection._sc)  csc.setConf(s"${cluster}/spark.cassandra.connection.host", host) csc.setConf(s"${cluster}/spark.cassandra.connection.port", port) csc.setConf(s"${cluster}/spark.cassandra.auth.username", username) csc.setConf(s"${cluster}/spark.cassandra.auth.password", password)  csc.read.format("org.apache.spark.sql.cassandra")                   .options(Map("cluster" -> cluster, "keyspace" -> keySpace, "table" -> table))                   .load() 

I tried with mention properties, Clusters those doesn't require authentication is connecting successfully but when i try to connect with secure cluster using username & password properties, i am getting some error.

Exception in thread "Thread-10" java.io.IOException: Failed to open native connection to Cassandra at {192.168.1.17}:9042     at com.datastax.spark.connector.cql.CassandraConnector$.com$datastax$spark$connector$cql$CassandraConnector$$createSession(CassandraConnector.scala:162)     at com.datastax.spark.connector.cql.CassandraConnector$$anonfun$2.apply(CassandraConnector.scala:148)     at com.datastax.spark.connector.cql.CassandraConnector$$anonfun$2.apply(CassandraConnector.scala:148)     at com.datastax.spark.connector.cql.RefCountedCache.createNewValueAndKeys(RefCountedCache.scala:31)     at com.datastax.spark.connector.cql.RefCountedCache.acquire(RefCountedCache.scala:56)     at com.datastax.spark.connector.cql.CassandraConnector.openSession(CassandraConnector.scala:81)     at com.datastax.spark.connector.cql.CassandraConnector.withSessionDo(CassandraConnector.scala:109)     at com.datastax.spark.connector.rdd.partitioner.CassandraRDDPartitioner$.getTokenFactory(CassandraRDDPartitioner.scala:184)     at org.apache.spark.sql.cassandra.CassandraSourceRelation$.apply(CassandraSourceRelation.scala:267)     at org.apache.spark.sql.cassandra.DefaultSource.createRelation(DefaultSource.scala:57)     at org.apache.spark.sql.execution.datasources.ResolvedDataSource$.apply(ResolvedDataSource.scala:158)     at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:119)     at com.bdbizviz.pa.spark.util.ServiceUtil$.readData(ServiceUtil.scala:97)     at com.bdbizviz.pa.spark.services.SparkServices$$anon$1.run(SparkServices.scala:114)     at java.lang.Thread.run(Thread.java:745) Caused by: com.datastax.driver.core.exceptions.AuthenticationException: Authentication error on host /192.168.1.17:9042: Host /192.168.1.17:9042 requires authentication, but no authenticator found in Cluster configuration     at com.datastax.driver.core.AuthProvider$1.newAuthenticator(AuthProvider.java:40)     at com.datastax.driver.core.Connection$5.apply(Connection.java:250)     at com.datastax.driver.core.Connection$5.apply(Connection.java:234)     at com.google.common.util.concurrent.Futures$ChainingListenableFuture.run(Futures.java:861)     at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297)     at com.google.common.util.concurrent.ExecutionList.executeListener(ExecutionList.java:156)     at com.google.common.util.concurrent.ExecutionList.execute(ExecutionList.java:145)     at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:185)     at com.datastax.driver.core.Connection$Future.onSet(Connection.java:1174)     at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:1005)     at com.datastax.driver.core.Connection$Dispatcher.channelRead0(Connection.java:928)     at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)     at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)     at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)     at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)     at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)     at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)     at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:244)     at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:308)     at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:294)     at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)     at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:831)     at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:346)     at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:254)     at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)     ... 1 more 

0 Answers

Read More