即使我向它添加查询,Mongodb-hadoop-connector也会创建大量分区

时间:2016-07-08 04:47:59

标签: mongodb hadoop apache-spark

我有一个非常大的mongo表,我想用spark做一些分析它,它太大了,我不想加载整个数据库。但看起来它总是扫描整个数据库并将它们拆分成大量的分区,即使我将mongo.input.query传递给它。我使用mongo-hadoop加载它,我的代码如下所示:

val conf = new SparkConf().setAppName("Simple Application")
val sc = new SparkContext(conf)

val mongoConfig = new Configuration()

val beginDate = new Date(2016 - 1900,6,7)

println("the begin data is: =========== >" + beginDate)

val beginId = new ObjectId(beginDate, 0,0.toShort,0)

mongoConfig.set("mongo.input.uri",
    "mongodb://mymongoduri/mongodb.mongocollection")

val queryStr = """{"_id": {"$gt" : {"$oid":"beginDate" }}}""".replace("beginDate", beginId.toString)
mongoConfig.set("mongo.input.query", queryStr)
mongoConfig.set("mongo.input.fields", """{ "its.src":-1, "its._id":-1, "its.cid": -1}""")

val documents = sc.newAPIHadoopRDD(
  mongoConfig,                // Configuration
  classOf[MongoInputFormat],  // InputFormat
  classOf[Object],            // Key type
  classOf[BSONObject])        // Value type

val OUTPUT_PATH = if(ENV == Some("dev")){
  s"./result"
} else{
  s"s3://${OUTPUT_BUCKET}/output/graph/${beginDate}"
}

documents.saveAsNewAPIHadoopFile(
  OUTPUT_PATH,
  classOf[Object],
  classOf[BSONObject],
  classOf[BSONFileOutputFormat[Object, BSONObject]]
)

它最终导致s3中的大量空文件,这不是我预期的结果(而且浪费了很多钱)。

我已阅读该文档,它只说mongo.input.query filter the input collection with a query,我可以像我查询的那样加载数据吗?不只是过滤它们。

或者,我可以存储那些非空的分区吗?

2 个答案:

答案 0 :(得分:2)

用于mongo的

spark hadoop连接器总是读取整个集合并相应地进行分区,然后使用输入查询过滤对象。当您保存文档RDD时,它将始终保存分区,无论它是否为空。

您可以将RDD重新分区为1.或者使用documents.coalesce(1).saveAsNewAPIHadoopFile(....)

答案 1 :(得分:1)

我仔细检查了代码。我发现默认拆分器始终扫描整个数据库,而com.mongodb.hadoop.splitter.MongoPaginatingSplitter将在执行拆分时应用查询。

而且,我发现他们的wiki中有一些配置mongo.splitter.class

com.mongodb.hadoop.splitter.MongoPaginatingSplitter

此Splitter构建增量范围查询以涵盖查询。这个Splitter需要更多的工作来计算分割边界,但是当给出 mongo.input.query 时,它比其他分割器表现更好。

所以我认为这应该是我问题的最终答案。