Mongodb hadoop连接器创建了很多分区,即使我向其中添加了查询

Mongodb hadoop连接器创建了很多分区,即使我向其中添加了查询,mongodb,hadoop,apache-spark,Mongodb,Hadoop,Apache Spark,我有一个非常大的mongo表,我想用spark对它进行一些分析,它太大了,我不想加载整个数据库。但它看起来总是扫描整个数据库,并将它们分割成大量的分区,即使我将mongo.input.query传递给它。我正在使用加载它,我的代码如下所示: val conf = new SparkConf().setAppName("Simple Application") val sc = new SparkContext(conf) val mongoConfig = new Configuration(

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

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
使用查询过滤输入集合
,我可以按照我查询的内容加载数据吗?不仅仅是过滤它们


或者,我可以只存储那些不为空的分区吗?spark hadoop connector for mongo始终读取整个集合并相应地进行分区,然后使用输入查询过滤对象。在保存文档RDD时,无论它是否为空,它都会保存分区


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

spark hadoop connector for mongo始终读取整个集合并进行相应的分区,然后使用输入查询筛选对象。在保存文档RDD时,无论它是否为空,它都会保存分区


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

我非常仔细地检查了代码。我发现默认的拆分器总是扫描整个数据库,而当您进行拆分时,
com.mongodb.hadoop.splitter.MongoPaginatingSplitter
将应用查询

然后,我发现他们的wiki中的configuration
mongo.splitter.class
下有一些东西:

com.mongodb.hadoop.splitter.MongoPaginatingSplitter

此拆分器构建增量范围查询以覆盖查询。此拆分器需要更多的工作来计算拆分边界,但在给定mongo.input.query时,它的性能优于其他拆分器


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

我非常仔细地检查了代码。我发现默认的拆分器总是扫描整个数据库,而当您进行拆分时,
com.mongodb.hadoop.splitter.MongoPaginatingSplitter
将应用查询

然后,我发现他们的wiki中的configuration
mongo.splitter.class
下有一些东西:

com.mongodb.hadoop.splitter.MongoPaginatingSplitter

此拆分器构建增量范围查询以覆盖查询。此拆分器需要更多的工作来计算拆分边界,但在给定mongo.input.query时,它的性能优于其他拆分器


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

非常感谢,我已经尝试了coalesce(20),但是看起来将100k个分区合并成一个分区太难了,我正在尝试coalesce(10000)。coalesce(1000)。coalesce(100)。coalesce(20)。顺便问一下,有没有任何连接器不能读取整个集合?我只想查询其中的一部分。嗨,请阅读我的答案,spark hadoop连接器确实提供了一个拆分器来使用查询。你不需要扫描整个数据库,很好。我之前没有意识到。非常感谢,我已经尝试了coalesce(20),但是看起来将100k个分区合并成一个分区太难了,我正在尝试coalesce(10000)。coalesce(1000)。coalesce(100)。coalesce(20)。顺便问一下,有没有任何连接器不能读取整个集合?我只想查询其中的一部分。嗨,请阅读我的答案,spark hadoop连接器确实提供了一个拆分器来使用查询。你不需要扫描整个数据库,很好。我之前没有意识到这一点。