SparkSQL查询的执行速度比我的数据库慢

时间:2019-03-29 01:17:02

标签: apache-spark jdbc apache-spark-sql

问候,

我在Amazon EC2中创建了一个Spark 2.1.1集群,实例类型为m4.large,其中有1个主服务器和5个从属服务器启动。我的 PostgreSQL 9.5 数据库(t2.large)包含一个我要处理的超过20亿行和7列的表。我遵循了Apache Spark网站和其他各种来源中关于如何连接和处理这些数据的指导。

我的问题是Spark SQL性能比我的数据库要慢得多。我的sql语句(请参见下面的代码)在PSQL中大约需要21分钟,而Spark SQL大约需要42分钟才能完成。我的主要目标是衡量PSQL与Spark SQL的性能,到目前为止,我还没有获得期望的结果。我会很感激的。

谢谢

我尝试将fetchSize从10000增加到100000,缓存数据帧,将numpartition增加到100,将spark.sql.shuffle设置为2000,将群集大小加倍,并使用更大的实例类型,到目前为止,我还没有看到任何改进

val spark = SparkSession.builder()
                        .appName("Spark SQL")
                        .getOrCreate();
val jdbcDF = spark.read.format("jdbc")
                  .option("url", DBI_URL)
                  .option("driver", "org.postgresql.Driver")
                  .option("dbtable", "ghcn_all")
                  .option("fetchsize", 10000)
                  .load()
                  .createOrReplaceTempView("ghcn_all");

val sqlStatement = "SELECT ghcn_date, element_value/10.0 
FROM ghcn_all 
WHERE station_id = 'USW00094846' 
      AND (ghcn_date >= '2015-01-01' AND ghcn_date <= '2015-12-31') 
      AND qflag IS NULL 
      AND element_type = 'PRCP' 
ORDER BY ghcn_date";

val sqlDF = spark.sql(sqlStatement);

var start:Long = System.nanoTime;
val num_rows:Long = sqlDF.count();
var end:Long = System.nanoTime;
println("Total Row                : " + num_rows);
println("Total Collect Time Lapse : " + ((end - start) / 1000000) + " ms");

2 个答案:

答案 0 :(得分:2)

没有充分的理由让此代码在Spark上运行比单独使用数据库更快。首先,它甚至没有分发,因为您犯了和您don't partition the data之前一样的错误。

但是更重要的是,您实际上是从数据库中加载数据-结果,它必须至少完成尽可能多的工作(实际上更多),然后通过网络发送数据,然后数据必须由Spark解析,并进行处理。您基本上会做更多的工作,并期望事情会更快-这是不会发生的。

如果您想可靠地提高Spark的性能,则至少应:

  • 从数据库中提取数据。
  • 写入高效的(类似于S3)分布式存储。
  • 使用适当的存储区和分区来启用分区修剪和谓词下推。

那么您可能会有更好的缺乏。但是同样,在群集上对数据进行适当的索引编制也可以提高性能,而总成本可能更低。

答案 1 :(得分:1)

从SQL读取时设置 partitionColumn 非常重要。它用于并行查询。因此,您应该确定哪一列是您的partitionColumn。

例如,您的情况:

val jdbcDF = spark.read.format("jdbc")
                  .option("url", DBI_URL)
                  .option("driver", "org.postgresql.Driver")
                  .option("dbtable", "ghcn_all")
                  .option("fetchsize", 10000)
                  .option("partitionColumn", "ghcn_date")
                  .option("lowerBound", "2015-01-01")
                  .option("upperBound", "2015-12-31")
                  .option("numPartitions",16 )
                  .load()
                  .createOrReplaceTempView("ghcn_all");

更多参考: