Hadoop
为什么有外部表和内部表?区别是什么?
早期也是没有内部表和外部表的说法的,在传统的RDMS数据数据库领域中,如果想要对一个数据库表进行例如增删改查等操作,就需要在数据库引擎中规范建立对应的数据库表,并且把数据导入其中才可以操作。
但是随着行业、大数据组件的不断发展,这种传统的玩法已经不能满足使用了,因此就提出了能不能通过外部表的形式与外界任何形式的数据建立连接。
在hive中,我们只需要通过简单的create external table … location '/xxx/xxx’的sql语句就建立一张外部表,通过location可以指向任何兼容数据的位置。
外部表与内部表不同的是:删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复(MSCK REPAIR TABLE table_name)。
因为外部表真正的执行不在数据库引擎中,像一些删除操作、修改操作都是不太好支持的,所以还是具有一定的局限性。目前除了hive,还有clickhouse、doris、starrocks等等工具都支持外部表功能。
hadoop集群为什么会出现脑裂以及解决办法?
脑裂最简单的理解就是一山不容二虎,当Leader节点出现故障,系统开始改朝换代,当Follower 完成全部工作并且成为 Leader 后,原 Leader 又复活了(它的故障可能是暂时断开或系统暂时变慢,不能及时响应,但其NameNode 进程还在),并且由于某种原因它对应的 ZKFC 并没有把它设置为 Standby,所以原 Leader 还认为自己是 Leader,客户端向它发出的请求仍会响应,于是脑裂就发生了。
如果出现脑裂,意味着多个 Namenode 数据不一致,此时只能选择保留其中一个的数据。例如:现在有三台 Namenode,分别为 nn1、nn2、nn3,出现脑裂,想要保留 nn1 的数据,步骤为:(1)关闭 nn2 和 nn3(2)在 nn2 和 nn3 节点重新执行数据同步命令:hdfs namenode -bootstrapStandby(3)重新启动 nn2 和 nn3。
mapreduce能不能不要map只要reduce?
大数据技术的核心思想是分治;
分布式计算引擎的核心思想是分治+规约;
分治和规约体现在mapreduce 框架中,就是map +reduce
map是对一份大的数据集,切成小份后各个击破,里面封装着对每一条数据的处理逻辑,对于一些简单的应用来说把每一条数据转化成为想要的样子,就可以直接输出,不需要reduce 过程。但是,每条数据之间有交集,需要做聚合汇总,就必须有reduce 阶段。
reduce本质上是reduce By Key,将有相同Key的数据进行合并,在map 到reduce 的中间过程,会将map 的结果根据key 进行排序和重组,即sort,combine 也就是shuffle 过程。
所以,对于mapreduce 框架来说,reduce 阶段不可以脱离map 而单独存在,因为reduce 本质上是reduce by key ,必须要通过map 阶段来定义哪个是key,哪个是value,以此作为reduce 的输入。
在spark 中可以直接用reduce 吗?可以,他不需要map 来定义。
Spark
spark比mapreduce快的原因是什么?mapreduce就一定比spark慢嘛?
在早期spark还没有出现的时候,是没人觉得mapreduce慢的,直到spark的出现,让众多大数据开发人员眼前一亮,经过统计,某些情况下,spark的处理效率要比mapreduce快100倍。
内存计算:mapreduce在编程模型上,只有简单map和reduce,而且map阶段的所以数据都要写入到磁盘,导致磁盘io开销很大,速度也很慢,而spark是完全基于内存的计算框架,只有当内存溢出的时候,才会写入到磁盘,这减少了磁盘读写操作,提高了计算效率。
DAG调度:Spark使用DAG(Directed Acyclic Graph)调度引擎,可以在内存中构建一个DAG,以避免重复计算和数据复制。而MapReduce使用简单的Map-Shuffle-Reduce模型,不能充分利用资源,导致资源浪费。
数据结构:Spark支持弹性分布式数据集(RDDs),允许对数据进行多次处理,并在多个计算节点之间共享数据。而MapReduce只能处理一次MapReduce操作,并将中间结果写入磁盘,从而导致性能损失。
并行度:Spark的并行度更高,可以将数据分成更小的块进行处理。Spark还可以动态调整并行度,以根据数据的大小和计算节点的数量进行自适应优化。而MapReduce的并行度较低,只能使用固定数量的计算节点进行处理。
同时spark针对大量场景,提供了丰富的算子和api,让开发者使用更加灵活方便。
综上所述,Spark具有更好的性能和灵活性,适用于大规模数据处理和机器学习任务。
但是,spark也并非是一定就比spark慢,当做一个简单的数据转换,且只需要Map操作时,mapreduce的处理效率要比Spark高,因为Spark预处理和启动的成本比较高,MapReduce在处理大规模数据时仍然具有一定的优势,因为它可以处理更大的数据集并具有更高的容错性。
map和mapPartition的区别?
map函数说明:将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以说值的转换。
mapPartitions函数说明:将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处理,哪怕是过滤数据。
mapPartitions 与 map算子不同的是,map在同一个分区内,是把数据一个一个串行处理,一个处理完了之后才会处理下一个;mapPartitions是将数据进行分区,按照分区进行批处理,所以相对来说后者的性能比较高一些。mapPartitions起到了一个缓冲的作用,把所有的数据加载到分区内存里面才进行批处理,而且内存不会释放,这样如果数据量比较大,而内存有限的情况下可能会造成内存溢出OOM.
mapPartitions 与 map算子的区别?
1.数据处理角度
Map 算子是分区内一个数据一个数据的执行,类似于串行操作。而 mapPartitions 算子是以分区为单位进行批处理操作。
2.功能的角度
Map 算子主要目的将数据源中的数据进行转换和改变。但是不会减少或增多数据。
MapPartitions 算子需要传递一个迭代器,返回一个迭代器,没有要求的元素的个数保持不变,所以可以增加或减少数据。
3.性能的角度
Map 算子因为类似于串行操作,所以性能比较低,而是 mapPartitions 算子类似于批处理,所以性能较高。
但是 mapPartitions 算子会长时间占用内存,那么这样会导致内存可能不够用,出现内存溢出的错误。所以在内存有限的情况下,不推荐使用。
repartition和coalesce的区别?
rdd转换算子coalesce : 缩减分区;
根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率;
当 spark 程序中,存在过多的小任务的时候,可以通过 coalesce 方法,收缩合并分区,减少分区的个数,减小任务调度成本;
第一个参数为分区的数量,第二个参数是是否进行shuffle处理,默认为false。
repartition 转化算子:重新分区,比如处理后的数据重新扩大分区数量,提高并行度:
repartition的底层就是调用了coalesce方法,并设置进行shuffle操作 coalesce(numPartitions, shuffle = true);
对于缩减分区,不需要进行shuffle操作,使用coalesce算子;
对于扩大分区,需要进行shuffle操作,使用repartition算子。
Java
set和list的区别?给定一系列字符串,从集合的set和list中查询,如何查询出相关的数据?
在Java中,Set和List都是用于存储对象的集合,但它们有一些关键区别:
Set:
不允许包含重复的元素。
没有顺序(即不保证元素的迭代顺序)。
List:
允许包含重复的元素。
保持元素插入的顺序(即迭代时按照插入顺序)。
总结
重复性:Set不允许存储重复的元素,而List允许。
顺序性:Set不保证元素的顺序,而List保持元素的插入顺序。
查询效率:通常情况下,Set在查询方面比List更高效,尤其是使用HashSet时,其contains方法的时间复杂度为O(1),而ArrayList的contains方法时间复杂度为O(n)。
要从Set或List集合中查询出相关的数据,可以使用常见的集合操作方法,例如contains()方法。
package com.java.Test;
import java.util.ArrayList;
import java.util.HashSet;
public class SetListTest {
public static void main(String[] args) {
String a = "a";
HashSet<String> hashSet = new HashSet<>();
hashSet.add("a");
hashSet.add("b");
hashSet.add("c");
hashSet.add("c");
System.out.println(hashSet);
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("c");
System.out.println(arrayList);
if (hashSet.contains(a)) {
System.out.println("true");
} else {
System.out.println("false");
}
if (arrayList.contains(a)) {
System.out.println("true");
} else {
System.out.println("false");
}
}
}