当前位置: 首页 > news >正文

spark数据处理练习题番外篇【上】

一. 单选题(共23题,100分)

1. (单选题)maven依赖应该加在哪个文件中?

  • A. pom.xml
  • B. log4j.properties
  • C. src/main/scala.resource
  • D. src/test/scala.resource

正确答案:A:pom.xml;

Maven 依赖应该添加在 pom.xml 文件中,这是 Maven 项目的核心配置文件。

解释:

  • pom.xml (Project Object Model) 文件定义了项目的所有配置信息,包括项目依赖、插件、构建设置等
  • 依赖通常在 <dependencies> 标签内定义,每个依赖使用 <dependency> 标签,包含 groupId、artifactId 和 version 等信息
  • 其他选项的用途:
    • log4j.properties:日志配置文件
    • src/main/scala.resource:资源文件目录,不是配置依赖的地方
    • src/test/scala.resource:测试资源文件目录,同样不是配置依赖的地方

Maven 通过 pom.xml 文件管理项目的整个生命周期,包括依赖管理、构建过程和部署等。

2. (单选题)

1 val conf=new SparkConf()

2     .setMaster("local")

3    .setAppName("test")

4 var sc=new SparkContext(conf)

5 var data=sc.textFile("f:/00ppt/spark1/abc.txt")

如果要打包发布到spark集群里运行需要改哪些行,选出行号

  • A. 2 3 4 5
  • B. 2 5
  • C. 3 5
  • D. 2 4

正确答案:B:2 5;

解释:

当将Spark应用程序从本地开发环境打包发布到Spark集群运行时,需要修改以下行:

  1. 第2行:.setMaster("local") 需要修改或删除

    • 在本地开发环境中,使用"local"表示在本地运行Spark
    • 在集群环境中,应该删除这一行,让集群管理器(如YARN、Mesos或Spark Standalone)决定master
    • 或者可以将其修改为集群地址,但通常在提交时通过spark-submit命令指定更灵活
  2. 第5行:var data=sc.textFile("f:/00ppt/spark1/abc.txt") 需要修改

    • 本地文件路径"f:/00ppt/spark1/abc.txt"是Windows格式的本地路径
    • 在集群环境中,应该使用分布式文件系统路径,如HDFS路径:"hdfs://namenode:8020/path/to/file"
    • 或者使用集群可访问的共享存储路径

不需要修改的行:

  • 第3行:.setAppName("test") 应用名称可以保持不变
  • 第4行:var sc=new SparkContext(conf) SparkContext创建方式不需要改变

3. (单选题)

var lst1=List("zs"->170,"ls"->175)

var rdd1=sc.parallelize(lst1)

rdd1.sortByKey().foreach(println(_))

输出结果是

  • A.

    (ls,175)

    (zs,170)

  • B.

    (ls)

    (zs)

  • C.

    (170)

    (175)

  • D.

    (zs,170)

    (ls,175)

正确答案:A:(ls,175) (zs,170) ;

解释:

让我们分析代码的执行过程:

  1. 首先创建了一个包含元组的List:

    List("zs"->170, "ls"->175)

    这里的 -> 操作符创建了两个二元组:("zs",170) 和 ("ls",175)

  2. 将List转换为RDD:

    var rdd1 = sc.parallelize(lst1)
  3. 使用sortByKey()对RDD进行排序:

    rdd1.sortByKey()
    • sortByKey() 默认按照key进行升序排序
    • 这里的key是字符串("zs"和"ls")
    • 字符串按字典顺序排序,"ls"在字母表中排在"zs"前面
  4. 最后foreach打印每个元素:

    foreach(println(_))

其他选项都是错误的:

  • B只输出了key
  • C只输出了value
  • D没有经过排序

4. (单选题)

var lst1=List("zs"->170,"ls"->175)

sc.parallelize(lst1).sortBy(______).foreach(println(_))

输出结果是

(zs,170)

(ls,175)

请填空

  • A. x=>x
  • B. _._2
  • C. _._1
  • D. x=>x.split("->")[1]

正确答案:B:_._2;

解释:

在这种情况下,sortBy 根据的是元组的 第二个元素(value) 来进行排序。具体来说:

  • lst1 是一个包含元组的列表:("zs" -> 170, "ls" -> 175),其中 "zs" 和 "ls" 是键(key),170 和 175 是值(value)。
  • 使用 sortBy(_._2) 时,表示按照元组的第二个元素(即身高,170 和 175)进行排序。

为什么不是其他选项:

  • A. x => x:这会按整个元组的顺序排序,不是按键或值,因此不符合要求。
  • C. _._1:这表示按元组的第一个元素(即key)排序,结果会是按字母顺序排序,输出会是:
    (ls, 175) (zs, 170) 这和题目要求的输出不符。
  • D. x => x.split("->")[1]:这是不正确的,因为 x 是元组,而不是字符串,所以不能使用 split

5. (单选题)

哪种分区可能造成数据倾斜?1 Hash分区 2 Range分区 3 自定义分区

  • A. 仅1
  • B. 1,2,3
  • C. 仅1 ,2
  • D. 2,3

正确答案:B:1,2,3;

解释:

所有三种分区方式 (Hash分区、Range分区、自定义分区) 都可能导致数据倾斜,下面逐一说明:

  1. Hash分区: Hash分区是根据某个键的哈希值来决定数据分配的分区。数据倾斜可能发生的原因是:
  • 如果某些键的分布不均匀,某些分区可能会得到非常多的数据,而其他分区则相对较少。
  • 例如,如果某些键的出现频率很高,所有具有这些高频键的数据就会被分配到少数几个分区,造成负载不均衡。
  1. Range分区: Range分区按数据的范围将数据分配到不同的分区。数据倾斜发生的原因是:
  • 如果数据在某些范围内非常集中,可能会导致某个分区的负载远大于其他分区。
  • 比如,某个数值区间(如[1000, 2000])可能包含大量的数据,而其他区间则相对空闲,造成负载不均。
  1. 自定义分区: 自定义分区由用户定义分区规则,因此,如果用户设计的分区策略不合理,也可能导致数据倾斜。

  • 例如,如果按照某些不均匀分布的字段进行分区(如按用户ID分区,而ID分布不均),某些分区可能包含大量数据,而其他分区几乎没有数据。

6. (单选题)

var a1=Array(1,2,3,9,8,7,4,6,5)

    var range1=sc.parallelize(List(______________)).map((_,1))

    var rdd1=sc.parallelize(a1)

    rdd1.map((_,1)).partitionBy(new RangePartitioner(3,range1))

选择合适的内容填空使数据尽量不倾斜

  • A. 1,3,6
  • B. 1,9,4
  • C. 2,8,6
  • D. 3,6,9

正确答案:D:3,6,9;

解释:

这个问题涉及到使用 RangePartitioner 进行数据分区,目标是避免数据倾斜。让我们分析一下代码和各个选项:

var a1 = Array(1, 2, 3, 9, 8, 7, 4, 6, 5) var range1 = sc.parallelize(List(______________)).map((_, 1)) var rdd1 = sc.parallelize(a1) rdd1.map((_, 1)).partitionBy(new RangePartitioner(3, range1))

在这段代码中:

  1. 我们有一个数组 a1,包含 9 个元素:1, 2, 3, 9, 8, 7, 4, 6, 5
  2. 需要创建一个 RDD range1,其中包含一些关键的分区边界值
  3. 然后使用 RangePartitioner 将 rdd1 分成 3 个分区

RangePartitioner 的工作原理

  • RangePartitioner 会根据提供的样本数据(这里是 range1)确定分区边界
  • 它会尝试将数据均匀地分布在各个分区中

为了避免数据倾斜,我们需要选择能够将原始数据 a1 均匀分配到 3 个分区的边界值。

分析选项 D: 3,6,9

  • 如果选择 3, 6, 9 作为边界值,RangePartitioner 会创建以下分区:
    • 分区 1: 小于或等于 3 的值 —— 包含 1, 2, 3(共 3 个元素)
    • 分区 2: 大于 3 且小于或等于 6 的值 —— 包含 4, 5, 6(共 3 个元素)
    • 分区 3: 大于 6 的值 —— 包含 7, 8, 9(共 3 个元素)

这样,9 个元素被均匀地分配到 3 个分区中,每个分区包含 3 个元素,实现了最佳的负载均衡,避免了数据倾斜。

其他选项的问题

  • 选项 A (1,3,6): 分区 1 包含 1 个元素,分区 2 包含 2 个元素,分区 3 包含 6 个元素,不均衡
  • 选项 B (1,9,4): 这些值不是有序的,不适合作为 RangePartitioner 的边界值
  • 选项 C (2,8,6): 这些值也不是有序的,不适合作为边界值

7. (单选题)

自定义分区类的设计,按key的首字母分区,a-g在0区,h-n在1区,o-t在2区,u-z在3区,请填空

class MyPartitioner1(n:Int) extends Partitioner{

  override def numPartitions: Int = __________

  override def getPartition(key: Any): Int = {

  var ch=key._______________

    if(ch<='n')

      if(ch<='g') 0

      else 1

    else

      if(ch<='t') 2

      else 3

  }

}

  • A.

    n        _.1

  • B. n       _.2
  • C. n        toString().charAt(0)
  • D. 4        element(0)

正确答案:C:n toString().charAt(0);

需求分析:

  1. 这是一个自定义分区器,根据key的首字母将数据分成4个区:

    • a-g: 区0
    • h-n: 区1
    • o-t: 区2
    • u-z: 区3
  2. 需要填写两个空:

    • 第一个空:需要返回分区数
    • 第二个空:需要获取key的首字母

解答分析:

  1. 第一个空 numPartitions

    • 根据分区逻辑,总共有4个分区(0,1,2,3)
    • 虽然构造函数接收参数n,但这里实际分区数是固定的4个
    • 应填 n(保持构造函数参数的一致性)
  2. 第二个空 getPartition 方法中的代码

    • 需要获取key的首字母
    • key是Any类型,需要先转换为字符串
    • 然后获取第一个字符
    • 应填 toString().charAt(0)

选项分析:

A. n, _.1

  • _.1 语法不正确,无法获取字符串首字母

B. n, _.2

  • _.2 语法不正确,无法获取字符串首字母

C. n, toString().charAt(0)

  • n 正确,表示分区数
  • toString().charAt(0) 正确,可以获取任意key的首字母

D. 4, element(0)

  • 4 虽然是实际分区数,但不符合构造函数参数设计
  • element(0) 语法不正确

8. (单选题)

spark-core中计算中采用了惰性求值方案,其中行动操作有()

1 count() 2 collect() 3 take()  4 first() 5 foreach() 

  • A. 1,2,3,4,5
  • B. 1,2,4
  • C. 1,3,5
  • D. 2,3,4,5

正确答案:A:1,2,3,4,5;

解释:

在Spark中,操作可以分为两类:

  1. 转换操作(Transformations):惰性操作,不会立即执行
  2. 行动操作(Actions):触发实际计算的操作

让我们分析每个选项中的操作:

  1. count()

    • 是行动操作
    • 返回RDD中元素的数量
    • 会触发实际计算
  2. collect()

    • 是行动操作
    • 将RDD中的所有元素收集到驱动程序中
    • 会触发实际计算
  3. take()

    • 是行动操作
    • 返回RDD中的前n个元素
    • 会触发实际计算
  4. first()

    • 是行动操作
    • 返回RDD中的第一个元素
    • 相当于take(1)
    • 会触发实际计算
  5. foreach()

    • 是行动操作
    • 对RDD中的每个元素执行指定操作
    • 会触发实际计算

其他常见的行动操作:

  • reduce()
  • aggregate()
  • fold()
  • saveAsTextFile()
  • countByKey()
  • foreach()

转换操作(Transformations)示例:

  • map()
  • filter()
  • flatMap()
  • groupBy()
  • union()
  • intersection()

行动操作的特点:

  1. 会触发实际的计算
  2. 会返回结果给驱动程序
  3. 导致之前的所有转换操作被执行

惰性求值的好处:

  1. 优化执行计划
  2. 减少不必要的计算
  3. 提高效率

9. (单选题)

关于spark-core说法正确的有()

1 当需要对RDD进行reduceByKey和filter,应该先filter

2 当需要对RDD按key值聚合运算,可以用reduceByKey也可以用groupByKey

3 选项2中,用reduceByKey效率更高

4 可以通过持久化(缓存)机制避免重复计算的开销

  • A. 1,2,3,4
  • B. 1,2,3
  • C. 2,3,4
  • D. 1,3,4

正确答案:A:1,2,3,4;

让我们逐条分析这些说法:

  1. "当需要对RDD进行reduceByKey和filter,应该先filter" - ✓正确

    • 原因:
      • filter操作会减少数据量
      • 先执行filter可以减少后续reduceByKey处理的数据量
      • 这符合Spark的优化原则:尽早减少数据量
  2. "当需要对RDD按key值聚合运算,可以用reduceByKey也可以用groupByKey" - ✓正确

    • 两者都可以实现按key聚合
    • reduceByKey: 在map端先进行combine,再进行reduce
    • groupByKey: 直接在reduce端进行分组
  3. "用reduceByKey效率更高" - ✓正确

    • 原因:
      • reduceByKey在map端有预聚合(combine)操作
      • 减少了网络传输的数据量
      • 而groupByKey需要传输所有数据到reduce端
  4. "可以通过持久化(缓存)机制避免重复计算的开销" - ✓正确

    • 通过cache()或persist()方法实现
    • 可以将RDD存储在内存或磁盘中
    • 避免多次计算同一个RDD
    • 特别适用于迭代计算场景

10. (单选题)

JSON 语法规则正确的是()

1 数据在key-value对中  2  数据由逗号分隔 3  大括号 {} 保存对象4 中括号 [] 保存数组,数组可以包含多个对象

  • A. 1,2,3
  • B. 1,2,3,4
  • C. 2,3,4
  • D. 1,3

正确答案:B:1,2,3,4;

让我们详细分析 JSON 的语法规则:

1. 数据在 key-value 对中 ✓

  • 格式:"key": value
  • 示例:

{ "name": "John", "age": 25 }

2. 数据由逗号分隔 ✓

  • 多个 key-value 对之间使用逗号分隔
  • 数组元素之间使用逗号分隔
  • 示例:

{ "name": "John", "age": 25, "city": "New York" }

3. 大括号 {} 保存对象 ✓

  • 对象以 { 开始,以 } 结束
  • 示例:

{ "person": { "name": "John", "age": 25 } }

4. 中括号 [] 保存数组,数组可以包含多个对象 ✓

  • 数组以 [ 开始,以 ] 结束
  • 示例:

{ "people": [ { "name": "John", "age": 25 }, { "name": "Mary", "age": 30 } ] }

11. (单选题)

    val rdd1=spark.sparkContext.parallelize(

      List(Person0("tom",21),Person0("zs",19),Person0("ls",20)) )

    val df1=rdd1.toDF()

    df1._______________________("person0")

    val res1=spark.sql( "select * from person0 where age>20")

    res1.show()

  }

case class ________(name:String,age:Int)

  • A. createSQLTable        Person0
  • B. querySQLString        Person1
  • C. createSQLTable       Person
  • D. createOrReplaceTempView        Person0

正确答案:D:createOrReplaceTempView Person0;

为什么 createOrReplaceTempView 是正确的?

  • createOrReplaceTempView 用来将一个 DataFrame 注册为一个临时视图或表,允许我们在 SQL 查询中使用它。
  • 这个临时视图只会在当前 Spark 会话中有效。

选项分析:

  • A: createSQLTable Person0:这个方法不存在,Spark没有提供名为 createSQLTable 的方法。
  • B: querySQLString Person1:同样,querySQLString 不是 Spark 的有效方法。
  • C: createSQLTable Person:同样,createSQLTable 并不是一个有效的方法。
  • D: createOrReplaceTempView Person0:正确,createOrReplaceTempView 是 Spark 中注册临时视图的方法。

相关文章:

  • Spring Boot集成Mina的Socket资源管理:从稳定通信到高性能优化
  • Windows上SSH连接Ubuntu失败
  • XWPFTemplate生成word
  • 置信水平、置信区间
  • 一体系数据平台的进化:基于阿里云 EMR Serverless Spark的持续演进
  • ESP32读取DHT11温湿度数据
  • 带eachers的html转word
  • 笔记 操作系统复习
  • 小程序的工具库-miniprogram-licia
  • AWS S3 SDK FOR JAVA 基本使用及如何兼容七牛云
  • 云计算——弹性云服务器(ECS)和裸金属服务器(BMS)
  • 小程序中的状态管理库-mobx-miniprogram
  • CentOS下的运维监控Grafana部署
  • 云计算——弹性云计算器(ECS)
  • 小程序动画性能提升指南:CSS硬件加速与JavaScript动画框架对比
  • Docker 运行 Kafka 带 SASL 认证教程
  • CARSIM-车速、油门、刹车练习
  • 破界协同:解锁电商平台混合云架构的双引擎效能
  • 微信小程序之bind和catch
  • Qt5 框架 CMake 探秘
  • 厦门网站建设哪家好/培训心得体会万能模板
  • 网站幻灯片效果代码/百度收录提交入口地址
  • 做网站赤峰/seo推广方式是什么呢
  • 网站建设的公司实习做什么/潍坊百度关键词优化
  • 网站建设 发票名称/网站seo谷歌
  • 一家公司做两个网站吗/自己建网站详细流程