1. MapReduce中Shuffle的执行流程是什么样的?  

- 阶段:Map端Shuffle、Reduce端Shuffle
- 功能:分区、排序、分组

Map端Shuffle

  1. 分区(Partition):在这个阶段,Map任务会调用分区器,根据Key的Hash值取模,以确定数据将进入哪个Reduce分区。
  2. 溢写(Spill):分区后的数据会被放入一个内存缓冲区。当缓冲区达到80%的阈值时,数据会被锁定并进行以下操作:
    • 排序:使用内存中的快速排序算法,将相同分区的数据放在一起,并在每个分区内按照Key进行排序。
    • 溢写:将排序好的数据写入磁盘,形成多个有序的小文件。
  3. 合并(Merge):每个Map任务会将自己生成的所有小文件合并成一个整体有序的大文件。在此过程中,会在磁盘中进行归并排序,将相同分区的数据放在一起,并在每个分区内按照Key进行排序。

Reduce端Shuffle

  1. 拉取(Pull):每个Reduce任务都会从每个Map任务生成的文件中读取属于自己的那部分数据。
  2. 合并(Merge):将拉取到的多份数据合并为整体有序的一份数据。在此过程中,会在磁盘中进行归并排序,按照Key进行排序。
  3. 分组(Group):按照Key进行分组,将相同Key的所有Value放入一个列表中。

2. YARN中MR程序运行的流程?

  1. 任务提交:客户端开始向ResourceManager提交MapReduce程序。

  2. 验证及启动:ResourceManager对提交的程序进行验证。如果验证通过,ResourceManager会随机选择一台NodeManager,并在其上启动Application Master。

  3. 资源申请:Application Master根据任务的需要,向ResourceManager申请运行任务所需的Container资源。

  4. 资源分配:ResourceManager根据当前资源状况,分配对应的Container,并将分配信息返回给Application Master。

  5. 资源分发:Application Master根据从ResourceManager接收到的Container信息,将这些信息分发给对应的NodeManager。

  6. 任务启动:NodeManager收到Container信息后,启动MapTask和ReduceTask。

  7. 任务监控:每个Task将其运行状态报告给Application Master。Application Master监控着每个Task的状态,直到任务结束。

  8. 任务结束:当所有Task都完成后,Application Master将运行结果返回。

3. YARN中的调度策略?

  1. FIFO (First In, First Out):这是最简单的调度策略,也是Hadoop 1.x系列的默认调度策略。在这种策略下,任务会按照提交到系统的顺序进行处理,即先提交的任务先运行。这种策略简单易实现,但是在处理大型、长时间运行的任务时可能导致资源利用率低和等待时间长。

  2. Capacity Scheduler:这是Apache Hadoop的默认调度器,它采用了多队列的设计,并在每个队列内部使用FIFO策略。每个队列都有固定的资源容量,当队列的资源没有被完全使用时,空余的资源可以被其他队列动态抢占。这种策略保证了资源的公平性和效率,但是需要进行适当的队列管理和配置。

  3. Fair Scheduler:这是Cloudera Hadoop(CDH)的默认调度器,它也采用了多队列的设计。但与Capacity Scheduler不同的是,Fair Scheduler 会在队列内部公平地分配资源,而不是先进先出。此外,它还支持动态资源抢占和权重分配,使得某些队列可以获得更多的资源。这种策略在处理多种不同类型和大小的任务时非常有效。

4. Hive的元数据有几种存储管理方式?

  1. 内嵌 (Embedded):这种方式使用Hive内置的Apache Derby数据库来存储和管理元数据。这种方式的好处是配置简单,不需要额外的数据库服务。但是,因为Derby数据库不支持多个访问实例,所以这种方式只适合于单用户的测试环境。

  2. 本地 (Local):这种方式使用一个外部的关系型数据库(如MySQL,PostgreSQL,Oracle等)来存储和管理元数据。外部数据库可以支持多用户并发访问,因此这种方式适合于生产环境。需要注意的是,选择这种方式需要自行维护数据库服务,包括安全,备份和性能优化等。

  3. 远程 (Remote):这种方式使用一个独立的Metastore服务来存储和管理元数据。Metastore服务可以运行在一个或者多个服务器上,并使用一个外部的关系型数据库来存储元数据。这种方式的好处是可以分离Hive和元数据的存储,提高系统的可扩展性和稳定性。同时,也可以支持更高级的功能,如权限管理,审计和元数据版本控制等。

5. Hive的计算引擎支持哪几种?

  1. MapReduce:这是Hive最初的计算引擎,也是许多早期Hadoop应用的基础。MapReduce模型简单易懂,非常适合处理大规模数据。然而,由于它的计算模型相对固定,且每个任务都需要读写磁盘,因此在处理复杂查询和交互式查询时,性能可能不尽如人意。

  2. Tez:Tez是为了解决MapReduce在复杂数据处理上的性能问题而设计的计算框架。Tez引擎可以将一个查询的多个阶段合并为一个Tez任务,从而避免了不必要的磁盘I/O,大大提高了查询效率。此外,Tez还支持动态的计算图,可以更好地适应各种查询模式。

  3. Spark:Spark是一种通用的大数据处理框架,它提供了比MapReduce更高级的计算模型,如RDD和DataFrame,以及丰富的计算库,如MLlib和GraphX。使用Spark作为Hive的计算引擎可以实现内存级的计算,大大提高了查询速度,特别是对于迭代式的数据处理任务。

6. Hive中常用的字符串函数有哪些?

  1. split(str, regex): 将字符串str按照正则表达式regex分割,返回一个数组。

  2. substr(str, pos, len): 从字符串str中提取出从位置pos开始,长度为len的子串。

  3. regexp_replace(str, regex, replacement): 将字符串str中符合正则表达式regex的部分替换为replacement

  4. concat(str1, str2, ...): 将两个或多个字符串连接在一起。

  5. concat_ws(separator, str1, str2, ...): 使用特定的分隔符separator将多个字符串连接在一起。

  6. length(str): 返回字符串str的长度。

  7. instr(str, substr): 返回子串substr在字符串str中第一次出现的位置。如果没有找到,返回0。

  8. reverse(str): 返回一个与输入字符串str相反的字符串。

  9. trim(str): 返回去掉输入字符串str两端的空格后的字符串。

7. Hive中常用的判断函数有哪些?

  1. CASE WHEN:这是一种条件判断语句,它允许你在查询中添加逻辑判断。结构是这样的:CASE WHEN condition THEN result [WHEN other_condition THEN other_result ...] [ELSE else_result] END。如果condition为真,则返回result;否则,如果other_condition为真,则返回other_result;如果所有条件都不为真,则返回else_result

  2. IF(testCondition, passValue, failValue):这是一个简单的条件判断函数,如果testCondition为真,就返回passValue,否则返回failValue

  3. NVL(testValue, replaceValue):这个函数会检查testValue是否为NULL。如果testValue为NULL,它会返回replaceValue;否则,它会返回testValue

  4. COALESCE(value1, value2, ...):这个函数从列表中返回第一个非NULL的值。如果所有值都是NULL,它将返回NULL。

8. Hive中常用的日期函数有哪些?

  1. datediff(enddate, startdate): 返回两个日期之间的天数差。enddatestartdate都应该是日期型的字符串。

  2. date_add(date, num): 在日期date上加上num天。

  3. date_sub(date, num): 在日期date上减去num天。

  4. from_unixtime(unixtime, format): 将UNIX时间戳unixtime转换为格式化的日期字符串。format参数是可选的,如果不提供,将使用默认的格式yyyy-MM-dd HH:mm:ss

  5. unix_timestamp(date, format): 将格式化的日期字符串date转换为UNIX时间戳。format参数是可选的,如果不提供,将假设date是默认的格式yyyy-MM-dd HH:mm:ss

  6. date_format(date, format): 将日期date转换为指定格式format的字符串。

  7. current_date(): 返回当前的日期,格式为yyyy-MM-dd

9. Hive中如何处理JSON数据?

  1. 通过函数处理

    • get_json_object(json_string, json_path):此函数可以从JSON字符串中获取数据。json_string是包含JSON数据的列,json_path是你想要获取的数据的JSON路径。

例如,假设你有一个名为my_table的表,其中有一列名为my_json,包含以下JSON数据:{"name":"John", "age":30, "city":"New York"}。那么,你可以使用以下查询来提取name字段:

SELECT get_json_object(my_json, '$.name') FROM my_table;

                2. json_tuple(json_string, path1, path2, ...):此函数用于从JSON字符串中提取多个值。json_string是包含JSON数据的列,path1path2, ... 是你想要获取的数据的JSON路径。

使用上面的例子,如果你想同时提取nameage字段,你可以使用以下查询:

SELECT name, age FROM my_table LATERAL VIEW json_tuple(my_json, 'name', 'age') jt AS name, age;

        2. JSON SerDe:SerDe是Serializer/Deserializer的简写,是Hive用来读写数据的接口。使用JSON SerDe,你可以直接创建一个JSON格式的表,然后加载JSON文件到这个表中。具体的创建表语句如下:

CREATE TABLE json_table (column1 type1, column2 type2, ...)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS TEXTFILE;

然后,你可以使用LOAD DATA语句将JSON文件加载到这个表中:

LOAD DATA LOCAL INPATH 'path_to_json_file' INTO TABLE json_table;

10. Hive中窗口函数有哪些,row_number(),rank()和dense_rank()的区别?

  1. 窗口聚合:这些函数可以在窗口内进行聚合操作。summaxminavgcount都可以在OVER子句中使用,以计算窗口内的总和、最大值、最小值、平均值和计数。

  2. 分析函数

    • row_number():在窗口内为每行分配一个唯一的整数,从1开始。即使有两行具有完全相同的排序值,这两行也会得到不同的行号。
    • rank():在窗口内为每行分配一个排名。如果两行具有完全相同的排序值,它们将得到相同的排名,下一个排名值将会跳过。
    • dense_rank():在窗口内为每行分配一个排名。如果两行具有完全相同的排序值,它们将得到相同的排名,下一个排名值将不会跳过。
    • ntile(n):在窗口内将行分成n个等大的组,每个组具有相同数量的行(如果可能)。
    • percent_rank():计算每行的百分比排名。
  3. 位置偏移

    • first_value:返回窗口内的第一个值。
    • last_value:返回窗口内的最后一个值。
    • lead:返回指定偏移量后的值。
    • lag:返回指定偏移量前的值。

11. 分区和分桶的区别是什么?

  1. 设计目的

    • 分区:主要用于提高查询效率。通过创建分区,你可以避免全表扫描,只检索特定分区的数据。
    • 分桶:主要用于解决随机数据采样、行级事务操作以及Reduce Join问题。
  2. 语法

    • 分区:使用PARTITIONED BY语句创建分区。
    • 分桶:使用CLUSTERED BY语句创建分桶。
  3. 实现方式

    • 分区:在目录级别进行数据划分。分区字段是逻辑字段,不会真正存储在数据文件中。
    • 分桶:在文件级别进行数据划分。分桶字段是物理字段,会真正存储在数据文件中。
  4. 使用场景

    • 分区:常规的数据查询和处理,特别是当你需要根据某些字段(如日期)频繁地过滤数据时。
    • 分桶:随机数据采样、行级事务操作以及Reduce Join操作。

12. Hive中的sort by、order by、distribute by和cluster by有什么区别?

  1. ORDER BY:这是最常见的排序操作,它会对输入进行全局排序。但是,因为只有一个reducer,所以当处理大量数据时,ORDER BY可能会导致性能瓶颈。

  2. SORT BYSORT BY也会对数据进行排序,但不保证全局排序。每个reducer会对其接收到的数据进行排序,但不同reducer间的数据可能不是有序的。因此,SORT BY通常比ORDER BY更快,但可能不会返回完全排序的结果。

  3. DISTRIBUTE BYDISTRIBUTE BY会根据指定的列对数据进行分区。每个分区将被发送到一个特定的reducer。DISTRIBUTE BY不会对数据进行排序,所以同一个分区内的数据可能是无序的。

  4. CLUSTER BYCLUSTER BYDISTRIBUTE BYSORT BY的结合。它首先根据指定的列对数据进行分区,然后在每个分区内进行排序。这样,同一个分区内的数据将是有序的。

13. 如何在Linux命令行执行Hive的SQL语句?

  1. hive -e:使用-e选项,你可以直接在命令行中执行Hive SQL语句。例如:

    hive -e 'SELECT * FROM my_table;'
    

    这个命令将执行SELECT * FROM my_table;这个Hive SQL语句,并将结果输出到命令行。

  2. hive -f:使用-f选项,你可以执行存储在文件中的Hive SQL语句。例如:

    hive -f /path/to/my_script.sql
    

    这个命令将执行/path/to/my_script.sql文件中的Hive SQL语句。

14. Hive中的优化有哪些?

  1. 参数优化

    • 本地模式(Local Mode):当处理小数据量时,可以尝试使用本地模式来避免Hadoop MapReduce的开销。在本地模式中,Hive会在单个JVM中直接运行查询。

    • 矢量化查询(Vectorized Query Execution):这种优化方式可以显著提高内存中数据的处理速度。它通过处理数据块(而非单个行)来达到这个效果。

    • 并行执行(Parallel Execution):Hive可以并行执行多个任务,例如MapReduce作业或子查询。这可以显著提高大规模查询的执行速度。

    • 推测执行(Speculative Execution):Hadoop可以在多个节点上复制同一个任务,当其中一个节点执行缓慢时,其他节点的结果可以被提前使用。这可以避免慢节点影响整个查询的执行时间。

    • 关联优化器(Join Optimizer):Hive可以根据表的大小和连接类型来重新排序连接操作,以提高查询性能。

    • 代价基础优化(Cost-Based Optimization,CBO):Hive可以使用CBO来生成更有效的查询计划。CBO会考虑各种因素,如数据大小、过滤器选择性等。

    • 零拷贝读取(Zero-Copy Read):这是一种优化读取性能的技术,它可以避免在读取数据时进行不必要的数据拷贝。

  2. 设计优化

    • 分区表(Partitioning):通过在表中创建分区,你可以将数据分成更小的部分,这样在查询时就只需要查找相关的分区,而不是整个表。

    • 分桶表(Bucketing):通过对表进行分桶,你可以根据哈希函数将数据分布到多个桶中。这可以提高某些类型查询的性能,例如采样查询和JOIN查询。

    • 文件格式(File Format):选择合适的文件格式可以提高查询性能。例如,Parquet和ORC是两种列式存储格式,它们可以提高列存储的查询性能。

    • 压缩格式(Compression Format):选择合适的压缩格式也可以提高查询性能,因为它可以减少存储和IO成本。不过,压缩数据可能会增加CPU使用率。

    • ORC索引优化:如果你使用ORC文件格式,你可以利用其内置的索引来提高查询性能。

  3. 开发优化

    • 基于谓词下推(Predicate Pushdown):这是一种优化查询的方法,它通过在数据源尽可能早的阶段应用过滤器来减少需要处理的数据量。

15. Hive中的数据倾斜怎么发现的?什么原因导致的?怎么解决?

  • 根本原因:分区的规则

    • 默认分区:根据Key的Hash值取余reduce的个数

    • 优点:相同的Key会由同一个reduce处理

    • 缺点:可能导致数据倾斜

  • 数据倾斜的场景:经过Shuffle过程中,数据重新分区

    • group by / count(distinct):分组

    • join:【Reduce Join】

  • 解决方案

    • 通用方案:调整Reduce个数:增大:适合于多个Key的数据全部集中在某个Reduce导致的数据倾斜

    • group by / count(distinct)

      • 开启Combiner,减少进入Reduce数据量,来避免数据倾斜

        hive.map.aggr=true
      • 随机分区

        • 方式一:开启参数

          hive.groupby.skewindata=true
          • 开启这个参数以后,底层会自动走两个MapReduce

          • 第一个MapReduce自动实现随机分区

          • 第二个MapReduce做最终的聚合

        • 方式二:手动指定,适合于这一步的结果并不是最终结果,一定后续还有程序会对当前数据的进行处理

          distribute by rand():将数据写入随机的分区中,避免数据倾斜
  • Join:避免走Reduce Join

    • 方案一:尽量避免走Reduce Join

      • Map Join:尽量将不需要参加Join的数据过滤,将大表转换为小表

      • 构建分桶Bucket Map Join

    • 方案二:skewjoin:避免数据倾斜的Reduce Join过程【==限制:外连接不生效==

08-05 15:22