spark-redshift需要花费大量时间才能写入redshift

时间:2016-03-02 06:09:39

标签: apache-spark spark-streaming amazon-redshift

我正在设置带有kinesis和redshift的火花流光。我每隔10秒就从kinesis读取数据,处理它并使用spark-redshift lib将其写入redshift。

问题是只花了很多时间才能写出300行。

这是它在控制台中显示的内容

[Stage 56:====================================================> (193 + 1) / 200]

查看我的日志df.write.format正在执行此操作。

我在装有4 gb ram和2核心amazon EC2的机器上安装了火花,并使用--master local [*]模式运行。

以下是我创建流的方式

kinesisStream = KinesisUtils.createStream(ssc, APPLICATION_NAME, STREAM_NAME, ENDPOINT, REGION_NAME, INITIAL_POS, CHECKPOINT_INTERVAL, awsAccessKeyId =AWSACCESSID, awsSecretKey=AWSSECRETKEY, storageLevel=STORAGE_LEVEL)    
CHECKPOINT_INTERVAL = 60
storageLevel = memory

kinesisStream.foreachRDD(writeTotable)
def WriteToTable(df, type):
    if type in REDSHIFT_PAGEVIEW_TBL:
        df = df.groupby([COL_STARTTIME, COL_ENDTIME, COL_CUSTOMERID, COL_PROJECTID, COL_FONTTYPE, COL_DOMAINNAME, COL_USERAGENT]).count()
        df = df.withColumnRenamed('count', COL_PAGEVIEWCOUNT)

        # Write back to a table

        url = ("jdbc:redshift://" + REDSHIFT_HOSTNAME + ":" + REDSHIFT_PORT + "/" +   REDSHIFT_DATABASE + "?user=" + REDSHIFT_USERNAME + "&password="+ REDSHIFT_PASSWORD)

        s3Dir = 's3n://' + AWSACCESSID + ':' + AWSSECRETKEY + '@' + BUCKET + '/' + FOLDER

        print 'Start writing to redshift'
        df.write.format("com.databricks.spark.redshift").option("url", url).option("dbtable", REDSHIFT_PAGEVIEW_TBL).option('tempdir', s3Dir).mode('Append').save()

        print 'Finished writing to redshift'

请让我知道花这么多时间的原因

2 个答案:

答案 0 :(得分:8)

我在使用Spark和直接写入Redshift时有过类似的经历。 spark-redshift将始终将数据写入S3,然后使用Redshift复制功能将数据写入目标表。这种方法是编写大量记录的最佳实践和最有效的方法。这种方法在写入时也会产生大量开销,特别是当每次写入的记录数量相对较小时。

查看上面的输出,看来你有大量的分区(大约200个左右)。这可能是因为spark.sql.shuffle.partitions设置默认设置为200。您可以找到更多详细信息in the Spark documentation

组操作可能会生成200个分区。这意味着您正在对S3执行200次单独的复制操作,每次操作都会在获取连接和完成写入时具有实质性的相关延迟。

正如我们在下面的评论和聊天中所讨论的那样,您可以将组的结果合并到更少的分区中,从而对上面的行进行以下更改:

df = df.coalesce(4).withColumnRenamed('count', COL_PAGEVIEWCOUNT)

这会将分区数从200减少到4,从副本到S3的开销减少几个数量级。您可以尝试分区数量以优化性能。您还可以更改spark.sql.shuffle.partitions设置,以根据您正在处理的数据大小和可用内核数量减少分区数。

答案 1 :(得分:0)

您是databrick API吗?这是众所周知的问题。我有同样的问题。我确实与Databric API团队交谈过。从Avaro文件加载时,似乎redshift没有提供良好的性能。我们确实与AWS团队进行了交流。他们正在努力。 Databrick API在S3上创建avaro文件,然后copy命令将加载avaro文件。这是性能杀手。