面试心经01--大数据开发工程师

37 篇文章 3 订阅
4 篇文章 0 订阅

1,MapReduce的工作流程

(1)input:输入文件
(2)split:客户端将每个block块切片(逻辑切分),每个切片都对应一个map任务,默认一个block块对应一个切片和一个map任务,split包含的信息:分片的元数据信息,包含起始位置,长度,和所在节点列表等;每一片都由一个MapTask来处理。
(3)map:按行读取切片数据,组成键值对,key为当前行在源文件中的字节偏移量,value为读到的字符串;map函数对键值对进行计算,输出<key,value,partition(分区号)>格式数据,partition指定该键值对由哪个reducer进行处理。通过分区器,key的hashcode对reducer个数取模。map将kvp写入环形缓冲区内,环形缓冲区默认为100MB,阈值为80%,当环形缓冲区达到80%时,就向磁盘溢写小文件,该小文件先按照分区号排序,区号相同的再按照key进行排序,归并排序。溢写的小文件如果达到三个,则进行归并,归并为大文件,大文件也按照分区和key进行排序,目的是降低中间结果数据量(网络传输),提升运行效率。
(4)shuffle:在map中,每个 map 函数会输出一组 key/value对, Shuffle 阶段需要从所有 map主机上把相同的 key 的 key value对组合在一起,组合后传给 reduce主机, 作为输入进入 reduce函数里。
(5)Reduce:每个reducer对应一个ReduceTask,在真正开始reduce之前,先要从分区中抓取数据;相同的分区的数据会进入同一个reduce。这一步中会从所有map输出中抓取某一分区的数据,在抓取的过程中伴随着排序、合并。
(6)output:输出结果。

2,数据倾斜产生的原因

数据经过 map后,由于不同key 的数据量分布不均,在shuffle 阶段中通过 partition 将相同的 key 的数据打上发往同一个 reducer 的标记,然后开始 spill (溢写)写入磁盘,最后merge成最终map阶段输出文件。
场景:
(1)其中一个表较小,但是key集中,分发到某一个或几个Reduce上的数据远高于平均值。
(2)大表与大表,但是分桶的判断字段0值或空值过多,这些空值都由一个reduce处理,非常慢。
(3)某特殊值过多,处理此特殊值的reduce耗时。
(4)group by 维度过小,某值的数量过多,处理某值的reduce非常耗时。
(5)不同数据类型关联产生数据倾斜

3,数据倾斜的解决方案

(1)在 map 阶段将造成倾斜的key 先分成多组,例如 aaa 这个 key,map 时随机在 aaa 后面加上 1,2,3,4 这四个数字之一,把 key 先分成四组,先进行一次运算,之后再恢复 key 进行最终运算。
(2)先进行 group 操作的时候先进行 group 操作,把 key 先进行一次 reduce,之后再进行 count 或者 distinct count 操作。
(3)join 操作中,使用 map join 在 map 端就先进行 join ,免得到reduce 时卡住;使用 map join 解决小表(记录数少)关联大表的数据倾斜问题,这个方法使用的频率非常高,但如果小表很大,大到map join会出现bug或异常,这时就需要特别的处理;对于join,在判断小表不大于1G的情况下,使用map join。
(4)尽量使用上述的SQL语句调节进行优化。

4,where 与 on 条件过滤的区别

(1)inner join: 当连接是inner join 的时候,where后面的过滤条件与关联on 后面的过滤条件所产生的效果是一样的。
(2)left join/right join: on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左(右)边表中的记录。(返回左(右)表全部记录)。此时可能会出现与右表不匹配的记录即为空的记录,即使on后边的条件不为真也会返回左(右)表中的记录;where条件是在临时表生成好后,再对临时表进行过滤的条件。

5,数据仓库的逻辑架构层次

(1)复制层:复制源系统(比如从mysql中读取所有数据导入到hive中的同结构表中,不做处理)的数据,尽量保持业务数据的原貌;与源系统数据唯一不同的是,SSA 中的数据在源系统数据的基础上加入了时间戳的信息,形成了多个版本的历史数据信息。
(2)原子层:基于模型开发的一套符合 3NF 范式规则的表结构,它存储了数据仓库内最细层次的数据,并按照不同的主题域对数据分类存储;比如高校数据统计服务平台根据目前部分需求将全校数据在 SOR 层中按人事、学生、教学、科研四大主题存储;SOR 是整个数据仓库的核心和基础,在设计过程中应具有足够的灵活性,以能应对添加更多的数据源、支持更多的分析需求,同时能够支持进一步的升级和更新。
(3)汇总层:由于 原子层是高度规范化数据,此要完成一个查询需要大量的关联工作,同时集市层/展现层中的数据粒度往往要比原子层高很多,对要生集市层/展现层中的汇总数据需要进行大量的汇总工作,此,汇总层根据需求把原子层数据进行适度的反范(例如,设计宽表结构将人员信息、干部信息等多表的数据合并起来)和汇总(例如,一些常用的头汇总、机构汇总等);从而提高数据仓库查询性能。
(4)集市层/展现层: 保存的数据供用户直接访问的:可以将集市层/展现层理解成最终用户接最终想要看的数据;DM 主要是各类粒度的事数据,通过提供不同粒度的数据,适应不同的数访问需求。

6,hive数据库基本概念

含义:Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。
优点:
	(1)Hive可以自由的扩展集群的规模,一般情况下不需要重启服务。
	(2)Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
	(3)良好的容错性,节点出现问题SQL仍可完成执行。
组件以及基本功能:
	(1)用户接口主要由三个:CLI、JDBC/ODBC和WebGUI。其中,CLI为shell命令行;JDBC/ODBC是Hive的JAVA实现,与传统数据库JDBC类似;WebGUI是通过浏览器访问Hive。
	(2)元数据存储:Hive 将元数据存储在数据库中。Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
	(3)解释器、编译器、优化器完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在 HDFS 中,并在随后有 MapReduce 调用执行。
Hive的数据存储:
	(1)Hive中所有的数据都存储在 HDFS 中,没有专门的数据存储格式(可支持Text,SequenceFile,ParquetFile,RCFILE等)
	(2)只需要在创建表的时候告诉 Hive 数据中的列分隔符和行分隔符,Hive 就可以解析数据。
	(3)Hive 中包含以下数据模型:DB、Table,External Table,Partition,Bucket。其中:db是在hdfs中表现为${hive.metastore.warehouse.dir}目录下一个文件夹; table是在hdfs中表现所属db目录下一个文件夹;external table是外部表, 与table类似,不过其数据存放位置可以在任意指定路径,普通表: 删除表后, hdfs上的文件都删了,External外部表删除后, hdfs上的文件没有删除, 只是把文件删除了; partition是在hdfs中表现为table目录下的子目录; bucket桶是在hdfs中表现为同一个表目录下根据hash散列之后的多个文件, 会根据不同的文件把数据放到不同的文件中。

7,hive数据库的基本操作

新建表结构:

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name

   [(col_name data_type [COMMENT col_comment], ...)]

   [COMMENT table_comment]

   [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]

   [CLUSTERED BY (col_name, col_name, ...)

   [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]

   [ROW FORMAT row_format]

   [STORED AS file_format]

   [LOCATION hdfs_path]

释义:

  1. CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
  2. EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
  3. LIKE 允许用户复制现有的表结构,但是不复制数据。
  4. 用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive通过 SerDe 确定表的具体的列的数据。
  5. 如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
  6. 对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

8,hive调优参数设置

(1)小表与大表关联,可以通过mapjoin来优化
	set hive.auto.convert.join = true ; //将小表刷入内存中
	set hive.mapjoin.smalltable.filesize = 2500000 ;//刷入内存表的大小(字节)
(2)group by 产生倾斜的问题,预先取100000条数据聚合,如果聚合后的条数/100000>0.5,则不再聚合
	set hive.map.aggr=true (开启map端combiner);
	hive.groupby.mapaggr.checkinterval = 100000 (默认)
	hive.map.aggr.hash.min.reduction=0.5(默认)
	set hive.groupby.skewindata=true;//决定 group by 操作是否支持倾斜的数据。注意:只能对单个字段聚合.控制生成两个MR Job,第一个MR Job Map的输出结果随机分配到reduce做次预汇总,减少某些key值条数过多某些key条数过小造成的数据倾斜问题
(3)reduce数太少
	set mapred.reduce.tasks=800; //默认是先设置hive.exec.reducers.bytes.per.reducer这个参数,设置了后hive会自动计算reduce的个数,因此两个参数一般不同时使用。
(4)key值都是有效值时,解决办法为设置以下几个参数
	set hive.exec.reducers.bytes.per.reducer = 1000000000  //每个节点的reduce 默认是处理1G大小的数据,如果你的join 操作也产生了数据倾斜,可以在hive 中设定。
	set hive.optimize.skewjoin = true; //hive 在运行的时候没有办法判断哪个key 会产生多大的倾斜,所以使用这个参数控制倾斜的阈值,如果超过这个值,新的值会发送给那些还没有达到的reduce, 一般可以设置成你(处理的总记录数/reduce个数)的2-4倍都可以接受。
	set hive.skewjoin.key = skew_key_threshold (default = 100000)//倾斜是经常会存在的,一般select 的层数超过2层,翻译成执行计划多于3个以上的mapreduce job 都很容易产生倾斜,建议每次运行比较复杂的sql 之前都可以设一下这个参数. 如果你不知道设置多少,可以就按官方默认的1个reduce 只处理1G 的算法,那么skew_key_threshold = 1G/平均行长. 或者默认直接设成250000000 (差不多算平均行长4个字节)。
(5)join的key值发生倾斜,key值包含很多空值或是异常值;
	对异常值赋一个随机值来分散key,通过rand函数将为null的值分散到不同的值上,在key值比较就能解决数据倾斜的问题,对于异常值如果不需要的话,最好是提前过滤掉,这样计算量可以大大减少。

9,SQL优化的方案

(1)使用索引可以提高相应的SQL查询效率,但同时也降低了 INSERT 及 UPDATE 的效。因为 INSERT 或 UPDATE 时有可能会重建索引,所以索引的设定需要慎重考虑。一个表的索引数最好不要超过 6 个。
(2)查询避免全表扫描,WHERE 及 ORDER BY 涉及的列尽量建立索引上。
(3)尽量用union all代替union,union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗及延迟。当然,union all的前提条件是两个结果集没有重复数据。
(4)in和exists、not in和not exists的使用,in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况;not in和not exists,推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。
(5)少使用select *  ,尽量指定需要查询的字段名称。
(6)limit  的合理使用。
(7)避免在where子句中对字段进行null值判断,对于null的判断会导致引擎放弃使用索引而进行全表扫描。
(8)%前缀模糊查询,这种查询会导致索引失效而进行全表扫描。
(9)合理使用索引,尽量使用小表驱动大表。
(10)避免在where子句使用or作为链接条件,可以使用union all。
(11)数据库在查询时,对 != 或 <> 操作符不会使用索引,可以使用union all。

10,数据库在进行多表连接时的处理算法

(1)hash join:hash-join就算讲两表中的小表(称S)作为hash表,然后去扫描另一个表(称M)的每一行数据,用得出来的行数据根据连接条件去映射建立的hash表,hash表是放在内存中的,这样可以很快的得到对应的S表与M表相匹配的行。hash-join只适用于等值连接。
(2)sort merge-join :merge join需要首先对两个表按照关联的字段进行排序,分别从两个表中取出一行数据进行匹配,如果合适放入结果集;不匹配将较小的那行丢掉继续匹配另一个表的下一行,依次处理直到将两表的数据取完。merge join的很大一部分开销花在排序上,也是同等条件下差于hash join的一个主要原因;对于结果集很大的情况,merge-join需要对其排序效率并不会很高。如果连接key本来就是有序的或者需要排序,那么可能用merge-join的代价会比hash-join更小,此时merge-join会更有优势。
(3)nested loop:嵌套循环连接,是比较通用的连接方式,分为内外表,每扫描外表的一行数据都要在内表中查找与之相匹配的行,没有索引的复杂度是O(N*M),这样的复杂度对于大数据集是非常劣势的,一般来讲会通过索引来提升性能;对于结果集很大的情况,nested loop join是一种嵌套循环的查询方式无疑更不适合大数据集的连接。对于>, <, <=, >=这样的查询连接还是需要nested loop这种通用的连接算法来处理。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓之以理的喵~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值