spark-mapPartitions

import org.apache.spark.{SparkConf, SparkContext}

import java.sql.DriverManager

/**
 * 将RDD中的数据,以分区为单位,进行相应的处理
 *
 * mapPartitions方法函数的输入是一个迭代器,函数的返回值也必须是迭代器
 *
 * mapPartitionsWithIndex可以将RDD的分区编号作为参数传入
 *
 */
object MapPartitionsDemo {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf().setAppName("WordCount").setMaster("local[5]")
    //1.创建SparkContext
    val sc = new SparkContext(conf)

        //商品ID,商品分类ID,商品金额
        var orders = List(
          (1,11,15.00),
          (2,12,31.00),
          (3,13,47.00),
          (4,14,99.00),
          (5,15,55.00)
        )

        val rdd1 = sc.parallelize(orders)

        //查询Mysql,关联维度数据,得到一个新的RDD
        //商品ID,商品分类ID,商品名称,商品金额
    //    val rdd2 = rdd1.map(e => {
    //      val cid = e._2
    //      //根据ID查找Mysql中维度的名称
    //      val connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/day0410?characterEncoding=utf-8", "root", "123456")
    //      val preparedStatement = connection.prepareStatement("select name from market where id = ?")
    //      preparedStatement.setInt(1, cid)
    //      val resultSet = preparedStatement.executeQuery()
    //      var name = "未知"
    //      if (resultSet.next()) {
    //        name = resultSet.getString(1)
    //      }
    //      (e._1, e._2, name, e._3)
    //    })
    //
    //    rdd2.saveAsTextFile("out1/01")

        val rdd2 = rdd1.mapPartitions(it => {
          //事先创建好连接
          val connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/day0410?characterEncoding=utf-8", "root", "123456")
          val preparedStatement = connection.prepareStatement("select name from market where id = ?")
          //一个分区中的多条数据用同一个连接对象
          it.map(e => {
            preparedStatement.setInt(1, e._2)
            val resultSet = preparedStatement.executeQuery()
            var name = "未知"
            if (resultSet.next()) {
              name = resultSet.getString(1)
            }
            (e._1, e._2, name, e._3)
          })
        })
        rdd2.saveAsTextFile("out1/01")

    /*val ints = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

    val rdd1 = sc.parallelize(ints, 2)
    val rdd2 = rdd1.mapPartitionsWithIndex((index, it) => {
      it.map(e => {
        s"partition: $index, element: $e"
      })
    })

    rdd2.saveAsTextFile("out1/02")*/

    sc.stop()
  }
}

map和mapPartitions的区别,mapPartitions一定会比map效率更高吗?

不一定:如果数据RDD中的数据进行简单的映射操作,例如变大写,对数据进行简单的运算,map和mapPartitions的效果是一样的,但是如果使用到了外部共享的对象或数据库连接,mapPartitions效率会更高。

原因:map出入的函数是一条一条的进行处理,如果使用数据库连接,会每来一条数据创建一个连接,导致性能过低;而mapPartitions传入的函数参数是迭代器,是以分区为单位进行操作,可以事先创建好一个连接,反复使用,操作一个分区中的多条数据。

特别提醒:如果mapPartitions方法不当,即将迭代器中的数据toList,就是将数据都放到内存中,可能会出现内存溢出的情况。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值