Spark到mongo db插入需要10小时才能获得60Gb数据

时间:2016-07-18 08:05:52

标签: mongodb apache-spark

我使用 Spark:1.6.2 MongoDB:3.2.8

我有一个包含8列和10亿行的数据帧。 shuffle写入数据帧是60GB。

我将使用mongo-spark-conector(mongo-spark-connector_2.10)在mongodb中插入该数据帧。

MongoSpark.write(sourceValueDf).options(mongoDbOptions).mode(SaveMode.Append).save();

对于插入,需要10个小时以上。

如何提高效果?

1 个答案:

答案 0 :(得分:4)

还有很多事情要做:

MongoSpark.write(sourceValueDf).options(mongoDbOptions).mode(SaveMode.Append).save()

但无论mongoDBOptions如何,调整都需要两倍,并且需要在Spark和MongoDB中修复性能瓶颈。成功的关键是了解运行上述代码时发生的情况,然后才能确定改善性能的最佳方法。

火花

  

我有一个包含8列和10亿行的数据帧。 shuffle写入数据帧是60GB。

sourceValueDf上没有任何信息,但您需要配置源并了解瓶颈是什么?请参阅Spark Monitoring文档,了解如何更好地了解Spark作业中发生的情况。

一般来说,Spark调整的关键点是; 分区缓存序列化 shuffle 操作。有关更多信息,请参阅cloudera的这篇精彩博文:Working with Apache Spark: Or, How I Learned to Stop Worrying and Love the Shuffle。如何改善星火作业有很多潜在的收获。

的MongoDB

让我们看一下MongoDB Spark连接器将使用的功能:

MongoSpark.write(sourceValueDf).options(mongoDbOptions).mode(SaveMode.Append).save()

此处连接器采用底层RDD,并使用以下逻辑将数据作为文档保存在现有数据库中:

rdd.foreachPartition(iter => if (iter.nonEmpty) {
    mongoConnector.withCollectionDo(writeConfig, { collection: MongoCollection[D] =>
    iter.grouped(DefaultMaxBatchSize).foreach(batch => collection.insertMany(batch.toList.asJava))
    })
})

对于每个分区,它将批量写入insertMany,每批使用512个文档(底层Java驱动程序批量大小)。 sourceValueDf中的分区数量较少会对保存的性能产生负面影响。增加分区数可能会增加此方法在Spark工作程序中的可并行性,从而增加吞吐量。

还有其他一些通用方法可以改善MongoDB批量操作的写入性能:

  • 网络

    确保Spark Workers和MongoDB实例共存或具有尽可能小的网络跃点。你无法击败物理学。

  • <强>拆分

    通过插入分片集合来增加写入的可并行性,尤其是在插入分片键上的数据时。 Spark工作人员与Sharded MongoD的共址可以提供最快的写入方案。有关配置选项的详细信息,请参阅连接器文档中的how can I achieve data locality部分。

  • <强>索引

    在插入数据之前删除索引并在之后重建它们。在插入大量数据时,用户通过在流程开始时删除索引,然后在结束时只构建一次索引,从而发现了性能改进。例如:

    val writeConfig = WriteConfig(mongoDbOptions)
    MongoConnector(writeConfig.asOptions).withCollectionDo(writeConfig, {
      coll: MongoCollection[Document] => coll.dropIndex("index")
    })
    
    MongoSpark.write(sourceValueDf)
              .options(writeConfig.asOptions)
              .mode(SaveMode.Append)
              .save()
    
    MongoConnector(writeConfig.asOptions).withCollectionDo(writeConfig, {  
      coll: MongoCollection[Document] => coll.createIndex(...)
    })
    
  • 写关注

    仅写入主节点而不是等待复制会以冗余为代价提高速度。这可以通过WriteConfig / mongoDbOptions进行配置。请参阅Output configuration documentation

运行此作业时,MongoDB计算机上的负载是多少?这是瓶颈吗?像MongoDB Cloud Manager这样的系统提供全面的性能可见性和监控,以帮助您了解MongoDB层发生的情况。

改善MongoDB和Spark性能

简而言之,没有万能药或魔术配置选项来帮助提高性能。它将需要调试,了解手头的问题,并可能考虑Spark和MongoDB集群的配置。它们一起被证明可以提供very fast compute and storage但它取决于使用情况和每个系统协同工作。

第一步是使用可用的监控工具来了解瓶颈的位置。