• 本文初衷是为了学习归纳,若有错误,请指出。

修改记录

时间内容
2020年4月10日第一次发布
2020年4月16日添加MaxCompute SQL部分
2020年9月14日新增数仓部分笔记

大数据架构

基础知识题

大数据组件概念

集群:多个人做同样的事

分布式:多个人协作,干不同的事情。

Hadoop:Hadoop是一个分布式存储和计算框架,具有高可靠, 高扩展, 高容错的特点(数据副本和集群);由底层HDFS分布式文件系统负责存储,和MapReduce负责分布式计算,以及后续增加的yarn负责资源协调管理。

Yarn:yarn是hadoop2.0为了分离资源管理和计算组件而引入的,yarn的诞生源于存储在HDFS的数据需要更多的交互模式,能提供更多的处理框架,而不单单是MR模式。

ZooKeeper:是一个分布式的,开放源码的,用于分布式应用程序的协调服务(service),基于观察者模式,接受观察者的注册,然后监听数据变化。

Hive:是由FaceBook开源的一个数据仓库工具,主要用于解决海量结构化日志的数据统计,可以将结构化的数据文件映射成一张表,并提供类似于SQL的查询方式来统计分析海量数据(主要离线分析),本质上是将HSQL转化成MapReduce程序。

在这里插入图片描述

参考文章:

《hadoop之hadoop用途方向》:https://blog.csdn.net/zhang123456456/article/details/77657807

《大数据基本概念》:https://www.sohu.com/a/259640251_741445

大数据环境搭建

1.介绍一下集群搭建的过程?
  • 下载hadoop 2.X,下载JDK1.8,安装CentOS7镜像,这里我自己是用VM虚拟机的环境来搭建三台集群。
  • 安装Linux系统并停掉防火墙,禁止SeLinux,配置时间同步定时刷新集群系统时间
  • 通过VM直接克隆出另外两台机器,配置IP地址,确保三台机器相互之间能ping通,能联网。
  • 然后增加专门用于hadoop的hadoop用户,为root用户和hadoop都配置ssh免秘钥登录
    • 首先修改/etc/hosts文件,每台机器都生成公钥秘钥,并把公钥拷贝到彼此之间的机器上
    • 然后集群机器互相验证免秘钥登录
    • 接着添加本地的公钥文件到自己的认证文件authorized_keys中,否则后续格式化hadoop可能报错。
  • 最后每台机器都安装hadoop和JDK,并添加对应环境变量,然后配置hadoop的四大核心配置文件(core-site.xml,hdfs-site.xml,mapred-site.xml,yarn-site.xml)
  • 取某一台机器做namenode节点进行格式化hadoop,接着启动hadoop验证集群是否搭建成功。

简述的过程是

安装CentOS7虚拟机 --> 配置IP、hosts文件和时间同步 --> 设置免秘钥登录 --> 安装hadoop --> 格式化hadoop --> 启动hadoop和运行mr程序

2.说一两个搭建过程遇到的坑?

hdfs namenode -format 格式化的时候失败过,一开始是ssh免秘钥登录的问题,后面又是yarn-site.xml配置文件的格式问题,最好从其它地方粘贴的配置代码先用工具格式化一下,并检查里面是否有中文符号

​ 另一个坑是虚拟机联网问题,我这里是用自定义网络然后选的vm-ware8,集群的IP一定要在同一网段,并且网关要和物理机上vm-ware8的IP地址相关联。

HDFS

1.请介绍一下HDFS?

​ Hadoop由三部分组成:HDFS、分布式计算MapReduce和资源调度引擎Yarn

​ HDFS 是一个分布式文件系统,负责文件存储。它的文件系统和平时看到的Linux很像,有目录结构,顶层目录是/,存放着文件,以及可以对文件进行增删,修改,移动等功能,不同的是它具有分布式的特点,hdfs的文件系统可以横跨多个机器,文件可能是存储在不同机器上的,但用户在使用时会被当作是存储在一台机器上。

​ HDFS具有高可用容错率高可扩展的特点。

​ 在HDFS中有一个核心概念-block块。

​ HDFS上的文件,是按照128M为单位,切分成一个个block的,分散的存储在集群的不同数据节点上。128M是指上限,实际可能block文件的大小不到128M。

​ 而为了保证数据的可用及容错,每一个block都可以设置副本数,默认是3,在集群搭建中,在hdfs-site.xml文件就可以设置默认副本数。每一个block的副本并不会存放在同一个服务器上面,而是分开存储在不同服务器,假如第一个block块暂时奔溃了,HDFS的主节点就会为了维持设置的block副本数,会重新在其它服务器上创建一模一样的block1。

​ HDFS的体系架构是典型的主从架构Master/Slave,有客户端和服务端,客服端通过NameNode主节点来访问存放在各个DataNode上的文件信息,NameNode负责管理每个子节点,同时还有secondaryNameNode做备份主节点。

​ 在NameNode管理每个DataNode过程中,有心跳机制能让namenade周期性地从集群中的每个datanode接受心跳信号和块状态报告,以便得知各集群节点是否正常运行,同时在hadoop集群刚启动时也会用到心跳机制,此时会先进入一个安全模式,等心跳确认99.9%的节点都正常后才进行正常工作,允许外界写入文件到HDFS。

​ HDFS有一个重要特性,那就是高可用,实现高可用最关键的是消除单点故障,会用到刚才体系架构中提到的SecondaryNamenode,概括来说就是当处于active状态的Namenode节点出问题后,他们之间有zookeeperFC会通知另一个暂时处于Standby状态的SecondaryNamenode准备替换工作,zookeeperFC是用来协调监控NameNode的,通知后原来的NameNode变成Standby状态,而SecondaryNamenode进行运行工作。

​ HDFS的联邦对应于HDFS的可拓展的特点,可以解决内存受限的问题,提高吞吐量和隔离不同类型的应用,但一般集群规模达到几千台的情况下才可能用到联邦(联邦,即支持多个NameNode主节点,每个Namenode分管一部分的元数据目录,并共享所有datanode存储资源)。

​ 至此HDFS概括性介绍完毕,对于HDFS的读写流程请翻看其它回答。

2.HDFS的机制是指什么,它有什么作用?

​ HDFS的机制是指它的心跳机制,我们知道HDFS是典型的Master/Slave主从架构,由一个Namenode管理多个Datanode过程中HDFS会用到它的心跳机制,其工作原理如下:

  • 1.首先master启动的时候,会开一个icp server;
  • 2.接着各个slave从节点启动时,连接上master,并且每隔3秒就向master发送一个icp server的”心跳“,携带状态信息;
  • 3.然后master通过这个心跳的返回值,得知从节点的状态,并向从节点传达命令。

心跳机制的作用有三点

(1)Namenode通过心跳机制全权管理数据,它周期性地从集群中的每个namenode接受心跳信号和块状态报告,有心跳意味着从节点工作正常,块状态报告中也会有该datanode上所有数据的列表。

(2)Datanode启动后向Namenode注册,并通过心跳上报数据块列表,3秒发送一次心跳,返回并执行Namenodede命令,如果10分钟都没有发送,代表这个Datanode出问题不可用。

(3)hadoop集群刚启动时会进入一个安全模式,这个安全模式也会用到心跳机制,只有Namenode得到99.9%datanode的反馈后安全模式才会解除。

3.请简述下HDFS文件的读写流程
  • HDFS读流程

    • 在获取文件名称后,运行在JVM虚拟机上的HDFS客户端,通过文件系统调用Namenode上的RPC方法(远程调用),让Namenode返回给客户端关于块的位置信息
    • 客户端获得位置信息后,就通过FSDataInputStream找到不同DataNode节点建立连接并读取数据
    • 数据源源不断的写入客户端,假设第一个block读取完成,就关闭指向该DataNode的连接,接着读下一个,以此类推。
    • 在读取数据过程中,存储在datanode的block本身有一个crc32位的校验码,当读取给客户端时会重新生成一个crc校验码,并对比前后两次校验码,相等说明读取的跟存入的是同一个文件。

    img

  • HDFS写流程

    客户端要向HDFS写数据,首先要跟namenode通信以确认可以写文件并获得接收文件block的datanode,然后,客户端按顺序将文件逐个block传递给相应datanode,并由接收到block的datanode负责向其他datanode复制block的副本

    在写入数据的过程中,底层会有一个data queue队列ack queue队列,写入数据时,block块是按一个一个字节来将数据写入到一个名为chunk的小块(chunk中包含4byte的校验值),写满chunk后再放到一个package中,后续每个package要加入到data queue队列。

    data queue中的package会逐步被发送到对应的datanode及其副本,同时还会复制一份写到ack queue队列中。待package写入完成后会重新生成校验值,这时拿新的校验值和ack queue中的package的校验值一一比对,如果比对成功,ack queue就删除对应package,如果比对不成功那么ack就把package发送回data queue再传输写入一次。

HDFS写流程
img

4.HDFS存储大量的小文件会发生什么问题?

​ 首先Namenode存储着文件系统的元数据,元数据记录了文件、块、目录,大约占150字节大小。如果hdfs的小文件过多,那么会占用元数据中记录文件的内存,给Namenode造成压力,影响hadoop存储和访问的效率。

​ 通常可以通过两种方法处理:

HAR文件方案:启动mr程序,通过hadoop archive命令将小文件压缩成一个har文件,适用于文件归档。

Sequence Files方案:还不太会用,暂不说明。

5.block块为什么设置比较大?是不是越大越好?

​ block的大小是由磁盘传输速度决定的,比如磁盘传输速度是200MB/S,那么block一般设定256MB。

​ 如果block太大,那么从磁盘传输数据的时间会明显变慢,另一方面,mapreduce中的map任务一般一次处理一个block块,如果块过大,mr的处理速度也会变慢。

​ 如果block太小,那么就会跟hdfs存储大量小文件的问题一样,会给namenode造成内存的压力。

MapReduce分布式计算

1.MapReduce的shuffle过程是怎么样的?

​ MapReduce的shuffle过程实际上包含在map阶段reduce阶段,也就是Map ShuffleReduce Shuffle

  • Map Shuffle的过程是对map的结果进行分区排序,然后按照同一分区的输出合并在一起写入到磁盘中,最终得到一个分区有序的文件。大致流程是:
    • 从map task输出的kv对数据会先写入到一个环形缓冲区,大小为100MB,但写满80%时就会溢出写入到磁盘文件
    • 在写入到磁盘文件的过程中,会对kv对进行HashPartition分区和排序,HashPartition是mr程序默认的分区方法,它会对kv对的key求hash值,然后对reduce的个数求模运算,最后得到的分区号作为分配给不同reduce的根据,分区后具有相同分区号的键值对存储在一起,每个分区里面的键值对又按key值进行排序。
    • 接下来会判断是否需要combine压缩具有同一键的键值对数据
    • 然后作为map输出准备传输给reduce
  • Reduce Shuffle过程中,是从reduce端通过网络传输向磁盘获取map输出开始,中间reduce shuffle也会把键相同的键值对数据放到一起,然后排序合并,最终形成一个整体有序的数据块,但这个过程是一直到调用reduce方法之前,也就是reduce shuffle并不包括调用reduce方法、
2.Combiner的作用

Combiner为了避免map task和reduce task之间的数据传输压力而设置的,它允许用户针对map task的输出指定一个合并函数,这个函数可以压缩具有同一key值的键值对,从而减少传输到reduce的数据量,减少网络带宽和reduce的负载。

​ 但实际上combiner是作为可选项,有没有设置或者设置多少次都不会影响最终结果,在shuffle过程中会判断是否设置而进行压缩。

3.如何诊断是否有数据倾斜存在并处理?

数据倾斜有两种原因:(1)某一个key对应的键值对数量要远远大于其它键的键值对数量;(2)部分数据记录的大小远超过平均值。

  • 可以在MR程序的reduce方法中追踪每个键的最大值,并且设置阈值,当超过该阈值时就可以认为发生了数据倾斜,可以输出到日志文件进行分析。

  • 第二种是很对编写MR程序时,从业务层面去考虑自定义的分区键是否合理。就跟ADS库建表时可以默认指定哪个字段作为分区键。

  • MR程序中改用TotalOrderPartitioner替换HashPartitioner,它可以通过对原始数据进行抽样得到的结果集来预设分区边界值,也就是能找出导致数据倾斜的key值,再分散处理。

  • MR程序中使用Combiner。

4.简述一下MapReduce的过程

​ MapReduce是采用一种分而治之的思想设计出来的分布式计算框架,它由两个阶段组成:map阶段和reduce阶段。

​ 在map阶段中:

  • 首先读取HDFS中的文件,每个文件都以一个个block形式存在,block中的数据会被解析成多个kv对,然后调用map taskmap方法
  • map方法对接收到的kv对进行分片处理,转换输出成新的kv对;
  • 然后对kv对进行分区和排序压缩,中间会涉及到map的shuffle过程,最后存入本地磁盘,供后续reduce task作为输入参数使用。

​ 在reduce阶段中:

  • reduce方法将多个map task的输出,按照不同的分区传输到不同的reduce 上进行合并排序,这中间也涉及到reduce的shuffle过程(shuffle就像洗扑克牌一样)
  • 然后reduce方法对输入的键值对汇总计算,输出计算结果
  • 最后把reduce的输出保存在HDFS文件中。

Yarn资源调度框架

1.介绍下Yarn的框架?(重要)

​ Yarn的框架也是经典的主从结构,和HDFS的一样,大体上yarn由一个ResourceManager和多个NodeManager构成,RM为主节点,NM为从节点。

ResourceManager是一个全局的资源管理器,负责整个系统的资源调度管理和分配,包括处理客户端请求、启动并监控ApplicationMaster,监控NodeManager,以及分配和调度资源。

​ 在ResourceManager中由两个组件构成: Schedule调度器ApplicationManager应用程序管理器

  • Schedule调度器会根据容量、队列等限制条件,对应用程序的资源需求进行资源分配。(调度器有三种:先进先出调度器,容量调度器和均分调度器
  • ApplicationManager则主要负责管理整个系统中所有应用程序,接受job请求,为应用分配一个Container来运行ApplicationMaster并管理,它和ApplicationMaster的区别是Master运行在NodeManger上的,而ApplicationManager是ResourceManager内部的一个组件。

ApplicationMaster负责管理yarn内运行的应用程序的每个实例,负责协调来自ResourceManager的资源,并通过NodeManager监控容器的执行和资源使用情况。

NodeManager在集群上有多个,它负责每个节点上的资源使用,处理ApplicationManager的请求,以及负责接受ResourceManager的资源分配命令,分配具体的Container给应用,同时还将Container的使用情况报告给ResourceManager。

​ 这里的Container实际上是一个资源抽象概念,代表系统上分配的资源,包括内存、磁盘、IO等。

具体过程如下:

​ 当客户端应用程序向ResourceManager提交应用需要的资源请求后,ResourceManager中的ApplicationManager接受到请求,并返回一个ContainerNodeManger,告诉NodeManager启动一个ApplicationMaster实例。

ApplicationMaster启动后向ResourceManager注册,此时客户端可以和ApplicationMaster直接交互,并告诉它需要的资源请求;后续ApplicationMaster继续发送资源请求给ResourceManager,待ResourceManager的Schedule处理后返回具体的Container信息,ApplicationMaster接收到资源信息后会分配给各个NodeManager来启动运行job任务(比如mr程序,内部是多个map task、reduce task)。

​ 在运行过程中,客户端和ApplicationMaster保持交互,可以得知程序的运行情况。ApplicationMaster此时主要监控和管理任务运行,而NodeManager会定时向ResourceManager汇报自身的运行状况和Container的使用信息,待程序运行完毕后,ApplicationMaster关闭,并向ResourceManager归还所有Container。

概括来说其过程如下

应用程序提交 --> 申请资源 --> 启动ApplicationMaster --> 申请运行任务的Container --> 分
​ 发Container --> 运行task任务 --> task任务结束 --> 回收Container。

另外还有JobHistoryServer(作业历史服务,记录在yarn中调度的作业历史运行情况) 和 Timeline Server(写日志数据),需要手动开启。

2.Yarn的动态性是指什么?

​ 是指多个应用程序的ApplicationMaster动态地和ResourceManager进行沟通,不断地申请资源,释放,再申请,再释放资源的过程。

3.Yarn的调度器有哪三种?他们的区别是什么?(重要)

​ yarn中有三种调度器选择:FIFO Scheduler(先进先出调度器),Capacity Scheduler(容量调度器),Fair Scheduler(均分调度器)

  • 三种调度器区别
    • hadoop1.x使用的默认调度器就是FIFO。FIFO采用队列方式将一个一个job任务按照时间先后顺序进行服务,比较好理解,哪个任务先进来就先完成它,在继续下一个任务。
    • hadoop2.x使用的默认调度器是Capacity Scheduler。Capacity Schedule调度器以队列为单位划分资源,队列有独立的资源,队列的结构和资源是可以进行配置的。
    • Fair Scheduler调度器会为所有job任务动态调整系统资源,且是平均分配的形式,让任务公平的共享集群资源

Zookeeper分布式协调框架

1.请简单介绍下Zookeeper?(重要)

​ ZooKeeper是一个分布式的,开放源码的,用于分布式应用程序的协调服务。

​ Zookeeper有攘其外,安其内的特点,也就只指它内部和谐统一,外部一致对外

​ 攘其外是指Zookeeper服务端有两种模式:单机的独立模式和集群的仲裁模式,所谓仲裁是指一切事件只要满足多数派同意就执行,不需要等到集群中的每个节点反馈才执行。Zookeeper本身也是服从主从架构的,在仲裁模式下会有一个主要的节点作为Leader(领导者),而其余集群中的节点作为Follower(公民),对某一事件是否执行,leader都会先征询各个follower的反馈信息再做决定,如果多数派同意,leader就将命令下发到所有的follower去执行。

​ 安其内是指Zookeeper的leader选举,leader的选举会发生在集群启动时和运行中leader挂了,概括选举过程也是少数服从多数选出新leader。

​ 在Zookeeper中的数据结构也是个重要概念,因为Zookeeper所提供的服务主要是通过它以下三部分组成:

Zookeeper = Znode(数据节点,也是简约版文件系统)+ 原语(可以理解成Zookeeper的命令) + Watcher(通知机制,类似监听器)

​ Znode可以分为持久节点临时节点,在用Zookeeper的命令create创建文件时默认时一个持久节点,而临时节点是会随着会话关闭而删除。另外也可以创建为有序节点,在创建时追加一个自增数字的标识。

Watcher通知机制类似于监听器的过程,即有注册 + 监听事件+ 回调函数,客户端在znode上注册一个Watcher监视器,当znode上数据出现变化,watcher监测到此变化就会通知客户端。在HDFS的HA高可用上也用到了Zookeeper的这种机制。

2.Zookeeper的工作原理?
3.Zookeeper读写流程:
  • 在Client向Follwer发出一个读写的请求
  • Follwer把请求发送给Leader,Leader接收到以后开始发起投票并通知每个Follwer进行投票
  • Follwer把投票结果发送给Leader
  • Leader将结果汇总后如果需要读取或写入,则开始执行同时把读写操作通知给Follwer,然后commit
  • Follower执行并把请求结果返回给Client
4.加入Zookeeper中某个Follower出故障了怎么办?(重要)

​ 这会启动Zookeeper的状态同步过程。具体来说如下:

​ 在完成leader选举后,各Follower和leader进行连接通信,并在每一次事务执行时,Follower都会把自己的最大事务ID发送给leader,当某个Follower出故障后,leader就根据原先该Follower发送的zxid确定同步点,向它同步记录最大zxid之后的内容。

​ 当完成同步后,会通知Follower已成为为update状态,Follower受到update消息后,就可以重新接受客户端的请求继续工作。

Hive

1.概括性地介绍一下Hive及其用法?(重要)

​ Hive主要解决海量结构化日志的数据统计分析,它是hadoop上的一种数据仓库工具,可以将结构化的数据文件映射成一张表,并提供类似于SQL的查询方式,本质上来说是将Hive转化成MR程序

  • Hive与其它数据库的区别:

    Hive数据是存储在HDFS,本质上是转换成mr程序执行,因此查询效率比较慢,涉及mr程序的资源调度和任务计算;HDFS的数据操作是支持覆盖追加,它不支持update和事务;扩展性好,可以在多个集群上做应用开发;Hive的读时速度快,因为在加载数据时并不会做数据校验,在读取数据时才会校验数据;处理数据规模大,适合于海量数据查询。

  • Hive的优缺点:

    • 优点:操作接口采用类SQL语法;不用写MR程序来计算;支持用户自定义函数
    • 缺点:不支持update和事务;查询延时严重。
  • Hive的架构原理

    • Hive首先是一个客户端工具,它提供了一些用户可操作的接口,可以通过交互shell,JDBC和web UI方式连接Hive,在Hive的内部有个Driver驱动器,驱动器里面实现了解析器,编译器,优化器和执行器的功能,在用Hsql查询表时,sql语句在驱动器中会先做语法和语义解析,解析之后再进行相应的语法编译,然后在通过优化器时产生逻辑计划和物理计划,并进行优化,最后在执行器中转换成对应的mr jar包,打包给hadoop集群运行获得结果.
    • 其中,在用SQL查询语句之前,Hive会将存放在hdfs的数据和对应的表建立映射关系,而记录这些映射信息和表结构信息的元数据,会存放在Hive指定的数据库中,比如mysql或者它自身warehourse目录下。
    • 大体流程如下:


​ 用户接口(shell、JDBC、Web UI) --> Driver(解析、编译、优化、执行)–> MR程序 --> hadoop集群

  • Hive的交互方式有三种:Hive交互Shell,Hive JDBC服务和Hive的命令

    • Hive交互Shell:直接输入在hive中/bin目录下的hive命令,进行sql查询

    • JDBC服务:

      • 启动hiveServer2服务:bin/hive --service hiveserver2

      • 然后 beeline命令连接hiveserver2:

        bin/beeline
        beeline> !connect jdbc:hive2://node1:10000
        
                  
                  
        • 1
        • 2
    • Hive命令:在hive命令后面加 -e 选项后,接sql查询语句即可。

      bin/hive -e "show databases;"
      
              
              
      • 1
  • Hive的数据类型和mysql的类似,常用的int、bigint、double、string、date、boolean,还有smallint、tinyint、float、varchar、timestamp,另外还有三种复合数据类型:array(数组),map(键值对),struct(一组命名的字段),复合类型在建表时需要特别指定。

  • Hive的建表操作

    • Hive的表可以分为外部表内部表,外部表创建时需要执行EXTERNAL关键字,它仅记录数据所在的存储路径,删除数据时外部表只是删除表的元数据,在重新建表后能直接关联上原来的数据,通常用作底层表;而内部表不需要指定EXTERNAL关键字,在删除数据后会把表的元数据和真实数据一起删除,通常用作中间表
    • 建表时建议指定分区,partitioned by,分区是把表的数据分目录存储在不同文件夹中,后期查询时可以避免全量扫描提升查询效率,可以指定一级分区,二级分区等;分区有动态和静态之分,在插入数据时可以给定具体的分区值做静态分区的方式插入,也可以只写明分区键做动态分区的方式插入,动态分区的方式会根据插入数据的值自动划分分区,但可能产生较多的小文件,浪费系统内存和IO。
    • 还可以指定分桶,Clustered by,分桶类似于将文件切分,它是将整个数据内容按照分桶键的值做hash算法,得出的结果再和分桶数做模运算来进行切分,指定了分桶表之后,后续select查询条件要加tablesample(bucket x out of y),适用于需要抽样调查的情况。
    • 最后建表时可以指定每一行中字段的分隔符,用”row format delimited fields terminated by“指定;可以指定文件存储类型,stored as 二进制文件,文本文件、或列式存储文件。以及指定表在hdfs上的存储位置location。
  • Hive数据的导入和导出

    • Hive数据导入:

      • 第一种,用load data导入数据:

        load data [local]  inpath  'dataPath'  override | into table student [partition 分区值];
        
                  
                  
        • 1
      • 第二种创建表时指定location数据路径,后面如果该路径本身有数据会导入到表中,如果是空文件可以用手动上传数据文件到hdfs中:

        hdfs fs -put /opt/bigdata/student.txt /user/hive/warehouse/student1

      • 第三种,可以在建表时as select * from 某张表,也可以insert into|override table时select * from某张表。

      • 最后一种是直接import table,导入某个数据文件,前提是数据文件要先export准备好。

    • Hive数据导出

      • 第一种是insert导出:可以insert导出到本地或者hdfs,还可以指定导出文件后的分隔符

        #加local导出到本地路径,默认文件分隔符时“\001”,之后本地会生成一个日志型的文件。
        insert override local directory '/opt/bigdata/student';
        #格式化导出文件
        insert override local directory '/opt/bigdata/student' row format delimited fields terminated by ',';
        #这里没有local
        insert override directory '/export/student' row format delimited fields terminated by ',';
        
                  
                  
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
      • 第二种是Hadoop命令直接下载,由于表和数据有映射关系,每张表在hdfs上都能找到对应数据存储位置,所以我们可以直接下载下来的,后期要检查下数据和分隔符是否有问题。

        hdfs fs -get /usr/hive/warehouse/student/student.txt /opt/bigdata/data
        
                  
                  
        • 1
      • 第三种是Hive shell命令导出,hive命令后面加-e或-f选项,再加sql查询语句指定到某个目录下,比如:

        #1.hive -e  “sql语句”  >> file; 这种是直接执行sql语句,把结果导出到文件中。
        #2.hive  -f  "sql文件"  > file; 这种是执行完sql文件后,将查询结果写入到file中
        

bin/hive -e ‘select * from default.student;’ >> /opt/bigdata/student.txt

  • 1
  • 2
  • 3
  • 4
  • 最后一种是export导出到hdfs

    hive>export table student to '/usr/hive/warehouse/student';
    
      
      
    • 1
  • Hive的文件存储格式和压缩方式:这里不做介绍,因为了解不深,只知道hive的压缩可以发生在map shuffle阶段中向磁盘写数据时压缩,以及reduce输出结果时作压缩。企业有效方式文件存储压缩是采用orc + snappy方式。

  • Hive的SerDe 序列化和反序列化,是使用Serde对行对象序列化和反序列化,方便数据加载到表中,最后实现把文件内容映射到hive表。如下所示:

    HDFS file -> InputFileFormat -> key,value -> Deserializer(反序列化) -> Row object

    Row object -> Serializer(序列化) -> key,value -> OutputFileFormat -> HDFS file

    建表时可以指定row format来使用SerDe。常用于企业解决多字符分割场景

  • 最后Hive重要的一点是Hive的调优,参考下面另一个问题的答案:8. 数据倾斜现象和解决办法?(重要)

  • 2. 将数据直接传到HDFS分区目录上,怎么让分区表和数据产生关联?

    因为上传到hdfs后,hive没有对应元数据信息所以无法查询到对应数据。可以上传数据后给分区表添加该目录的分区

    dfs -mkdir -p 分区目录
    dfs -put 分区数据
    hive>alter table 表明 add partition(分区);
    
     
     
    • 1
    • 2
    • 3
    3. 桶表是否可以直接通过load将数据导入?

    不可以,因为load数据的话hdfs下只会有一个文件无法完成分桶的效果,需要通过中间表导入数据

    4. hive的分区可以提高效率,那么分区是否越多越好?为什么?

    不是越多越好

    • hive底层是存储在hdfs上的,hdfs是适合存储大文件而不适合小文件,如果有越多的分区,那么会增加namenode的负担
    • hive会转化成mr程序,mr会转化为多个task任务,多个小文件的话,每个文件一个task,每个task运行一个JVM实例,JVM的开启和销毁都会降低系统性能。

    所以分区数要合理设计,一般在3个以内。

    5. 什么情况下Hive可以避免进行mapreduce?
    • 如果是进行简单的查询,直接select,不带count,sum这些聚合函数的,都不会走mapreduce,而是直接读取hdfs目录中的文件。(fetch抓取)
    • 另外如果查询语句中的过滤条件只是分区字段的情况下,也不会走mapreduce(fetch抓取)
    select * from order_partition where month = '2019-03';
    
     
     
    • 1
    • 还有就是可以手动设置,让hive使用本地模式,当然这种有限制,需要查询的文件不超过256M或者文件数量不超过4个,否则系统还是会自动走mapreduce
    set hive.exec.mode.local.auto = true;
    
     
     
    • 1
    6. order by ,sort by , distribute by , cluster by 的区别?

    Order by会对所给的全部数据进行全局排序,只启动一个reduce来处理。

    Sort by局部排序,它可以根据数据量的大小启动一到多个reducer来工作,并且在每个reduce中单独排序。

    Distribute by 类似于mr中的partition,采用hash算法,在map端将查询结果中hash值相同的结果分发到对应的reduce中,结合sort by使用

    Cluster by 可以看作是distribute by 和sort by的结合,当两者后面所跟的字段列名相同时,效果就等同于使用cluster by,但是cluster by最终的结果只能是降序,无法指定升序和降序。

    7. 如何将数据以动态分区的方式插入分区表中?
    • 1.首先创建对应分区表和一张普通表

    • 2.然后将数据加载到普通表

    load data local inpath '/opt/bigdata/order_partition' into table tt_order;
    
     
     
    • 1
    • 3.最后利用普通表来将数据加载到动态分区表中
    #先设置使用动态分区的参数和使用非严格模式
    set hive.exec.dynamic.partition=true;
    set hive.exec.dynamic.partition.mode=nonstrict; 
    

    #然后通过普通表导入分区表
    insert into table order_partition partition(year,month) select order_number,order_price,substring(order_time,0,4) as year,substring(order_time,6,12) as month from tt_order;
    #注意导入的字段顺序,分区键一定要放在最后,否则会报错。

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    8. 数据倾斜现象和解决办法?(重要)
    • 1.什么是数据倾斜?

      大量相同特征的key出现在同一个reduce任务中,或者某个key对应的数据量远超过其它key的数据量,这种导致数据分布不均匀的现象就叫做数据倾斜。

    • 2.数据倾斜的现象

      在执行任务的时候,任务进度长时间卡在99%左右,查看任务监控页面或者详细日志信息,发现只有少量,一个或者几个reduce子任务没有跑完,主要因为这几个reduce任务处理的数据量和其它reduce任务差异过大。这种单一reduce任务的记录数与平均记录数差异过大,就会极大拖长计算时间。

      现实工作中可能会遇到这样的情况比较多:比如大表join小表,其中小表有特别的key值比较集中,这样分发到某一个reduce上的数据就会高于平均值;或者是大表join大表中,作为连接判断的字段0值或者空值较多的,这些0值和空值后续都会由一个reduce处理,导致这个reduce处理量过多;再有的情况就是group by、**count( distinct )**某个字段值数据多而导致reduce处理耗时的情况。

    • 3.数据倾斜的原因

      • key分布不均匀,比如空值,0值
      • 业务数据本身的特性。
      • 建表时考虑不周,导致后期join操作时数据倾斜
      • 某些sql语句本身就有数据倾斜。比如用count(distinct),它会单独用一个reduce来计算统计,如果数据量很大,就会导致整个job很难完成。这种情况可以先用group by分出需要统计的字段,再进行sum或者count
    • 4.数据倾斜的解决方案,有三个层面可以思考处理:

      • 第一,SQL语句调优

        • 查询语句加上具体需要的列和分区键,有些复杂表的字段会存储json格式的文本,这些字段不一定是需要查询的就可以过滤掉,减轻reduce计算负担

        • 大表join小表时用map jion,让小表先进内存,然后大表与小表在map端完成join操作,避免reduce端处理。

        • 大表join大表中,可以把空值的key变成一个字符串然后加上rand()随机数,后续mr的分区操作会把倾斜的数据重新分发到不同的reduce上,从而避免数据倾斜。或者在join 的on条件中先让key为空的值 不参与关联,等key不为空的数据相互合并连接后再union all加回key为空的数据。

          select * from a left outer join b 
          on case where id is null then concat('任意字符串',rand()) else id end = b.id;
          

    select from log a join users b on a.id is not null and a.id = b.id
    union all
    selct from log a where a.id is null;

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 查询语句中count(distinct) 改成group by + sum(),比如

    select count(distinct id) from test; ==> select sum(id) from (select id from test group by id); 这种可能会多开一个reduce来完成group by的操作,但会明显提高查询速度。

  • 针对不同数据类型产生的数据倾斜,存在这样的情况,A表中的id字段的数据类型是int,但join的B表中id字段存在脏数据,有一些是int类型但也有string类型的,那么再join操作时,默认的hash操作就会对int类型的key进行分配,而对于string类型的key会被统一分配到一个reduce中,这种情况就需要先进行类型转换,如 a join b on a.id = cast(b.id as int);

  • 还有一些时候可以把数据倾斜的数据单独拿出来处理,然后再union all回去。

  • 第二,通过设置hive参数配置解决,这种主要是优化计算速度,避免数据倾斜发生

    • 开启map端聚合

      并不是所有的聚合操作都需要在reducec端完成,很多聚合操作都可以现在map端先进行部分聚合,最后在reduce端得出最终结果(类似于mr过程中的combiner,预先合并压缩数据,再提供给reduce统计计算)

      再hive开启map端聚合后,一旦发现数据倾斜,系统就能自动负载均衡,把相同特征的key分发到不同的reduce中,主要通过hive.groupby.skewindata参数完成。

      #开启map端聚合的设置
      #是否在map段進行聚合,默认是true
      set hive.map.aggr = true
      #在map端进行聚合操作的条目数目
      set hive.groupby.mapaggr.checkinterval = 100000;
      #有数据倾斜的时候进行负载均衡,比如把相同特征的key分发到不同的reduce中(默认是false)
      set hive.groupby.skewindata = true;
      
          
          
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 设置并行执行

      和oracle一样也可以利用并行执行提高查询速度,不同的是hive是靠参数来空值的

      #开启并行执行
      set hive.exec.parallel = true;
      #设置同一个sql允许的最大并行度,默认是8
      set hive.exec.parallel.thread.number = 16;
      
          
          
      • 1
      • 2
      • 3
      • 4
    • 设置压缩

      压缩可以在map端要进行shuffle时压缩和在完成reduce输出时压缩

      • Hive表中间数据压缩
      #设置为true为激活中间数据压缩功能,默认是false,没有开启
      set hive.exec.compress.intermediate = true;
      #设置中间数据的压缩算法
      set mapred map.output.compression = codec = org.apache.hadoop.io.compress.SnappyCodec;
      
          
          
      • 1
      • 2
      • 3
      • 4
      • Hive表最终输出结果压缩
      set hive.exec.compress.output = true;
      set mapred map.output.compression = codec = org.apache.hadoop.io.compress.SnappyCodec;
      
          
          
      • 1
      • 2
    • 推测执行

      说简单点就是Hadoop用了一个备份任务来同时执行,跟原来的任务相比较,谁先执行完成就用谁的计算结果作为最终的计算结果。具体定义如下:

      ​ Hadoop采用了推测执行机制,它根据一定的法则推测出”拖后腿“的任务,并为这样的任务启动一个备份任务,让备份任务和原始任务同时处理一份数据,并最后选择优先执行完成的任务计算结果作为最终结果。

      #开启推测执行机制
      set hive.mapred.reduce.tasks.speculative.exection = true;
      
          
          
      • 1
      • 2
    • JVM重用

      JVM重用可以使得JVM实例在同一个job中重新使用多次,减少进程的启动和销毁时间

      #设置jvm重用个数
      set mapred.job.reuse.jvm.num.tasks = 5;
      
          
          
      • 1
      • 2
    • 合理设置map数reduce数

      • 在map执行之前将小文件合并可以减少map数
      #系统默认的格式,可以不用设置。
      set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 
      
          
          
      • 1
      • 2
      • 复杂文件可以增加map数
      增加map方法有一个公式:
      compute(SliteSize(Math.max(minSize,Math.min(maxSize,blocksizs))))公式
      - 调整maxSize最大值,让maxSize小于blocksize就可以增加map数
      - minSize默认等于1,maxSize默认等于blockSize大小。
      
  • #比如这样设置就可以达到增加map数的效果
    #设置每个map处理的文件maxSize大小为10M,这样小于一个block128M的话,系统就会分配更多10M的map来处理复杂任务。
    set mapreduce.input.fileinputformat.split.maxsize = 10485760;

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 合理设置Reduce数,比如设置每个job中reduce的个数为3个
    set mapreduce.job.reduces = 3;
    
     
     
    • 1
  • 第三,修改MR程序去避免数据倾斜

    • 可以在MR程序的reduce方法中追踪每个键的最大值,并且设置阈值,当超过该阈值时就可以认为发生了数据倾斜,然后输出到日志文件进行分析。

    • 第二种是在编写MR程序时,从业务层面去考虑自定义的分区键是否合理。就跟ADS库建表时可以默认指定哪个字段作为分区键。

    • MR程序中改用TotalOrderPartitioner替换HashPartitioner,它可以通过对原始数据进行抽样得到的结果集来预设分区边界值,也就是能找出导致数据倾斜的key值,再分散处理。

    • MR程序中使用Combiner

  • 数据仓库

    1.介绍一下对数据仓库的理解?

    ​ 数据仓库是面向业务主题,为分析数据而设计的。

    ​ 通俗来讲,数据仓库就像生活中的普通仓库一样,能对物品集中管理、分类摆放、按需取用,最终目的都是为了更方便和更快速地查询到想要的数据结果,提供数据支持和决策支持。

    ​ 打比方:对多来源的数据做元数据管理就像对物品打标签一样,而ETL抽取的过程和数据分层建模的过程则类比物品分类摆放的过程,期间有些需要抽样研究的就作为数据挖掘和机器学习的数据,有些使用频率非常高的就单独拿来做实时查询,对于不怎么改动的历史数据就按主题抽取另外分析查询,而市面上像阿里云这类的平台工具就好比放物品的货架。

    ​ 总结来说,它的特点有:

    • 第一,面向主题:面向主题是指数仓中的数据是按照一定的业务主题划分组织的,能帮助用户做决策和分析探索。

    • 第二,集成性:数仓的数据来源于其他源系统,可以使用各种ETL工具集成汇总到数仓。

    • 第三,稳定性:数仓主要是为了决策分析,它存储大量的历史数据,一般只有新增,没有更新操作;

    • 第四,时变性:时变性是指它具有时间属性,可以不断生成主题的新数据,比如按年月日的增量数据。

    2.什么是维度、事实表、维度表、数据集市、粒度?
    • 粒度:粒度反映了数据仓库按照不同的层次组织数据,根据不同的查询需要,存储不同细节的数据,粒度越小,数据越细,查询范围就越广泛;粒度大就越不够细节。
    • 维度:看待事物的角度,
    • 维度表:一般是对事实的描述信息,可以看做是用户分析数据的窗口,包含了事实数据的特性。每一张维度表对应显示世界中的一个对象或者概念,比如用户类型、商品、日期、地区等。
    • 事实表:包含对分析事物的一个或多个度量值(指标)。
    • 指标:可以理解为统计的销售额、转账额等这样的业务统计数。
    • 度量:可以是事实表中存放数值型或者连续次数的字段。
    3.数据仓库系统的数据质量如何保证?
    4.描述一下OLTP和OLAP的区别
    • OLAP 联机分析处理
      • 是数据仓库系统最主要的应用
      • 数据量大,适合大数据量查询
      • 实时性要求不高、DML操作不频繁
      • 支持复杂的分析操作
      • 侧重决策支持
      • 并且提供直观易懂的查询结果
    • OLTP 联机事务处理
      • 是传统关系型数据库的主要应用
      • 数据量小
      • 要求实时、DML操作频繁
      • 并行事务处理多,强调数据库处理效率
    5.数据仓库常用的两种模型及其特点?
    • 星型模型:事实表和多个维度表关联,维度表的主键是事实表的外键,维度表不能继续拥有维度表。
      • 优点:逻辑简单,join时不需要关联太多表,有较好的查询性能
      • 缺点:维度表存储太多信息,数据冗余度大不利于扩展;另一个是需要做大量数据预处理工作
    • 雪花模型:在星型模型基础上,约定维度表可以继续向外延伸拥有维度表。
      • 优点:数据冗余度低,扩展性好
      • 缺点:当维度表的层次变多时,可读性差,并且发展到业务后期维护困难;join时关联多表查询性能较低。
    6.构建数仓应该有哪些过程?
    • (1)明确需求,分析数据的业务场景;
    • (2)分析数据结构,做好元数据管理。
    • (3)设计数据仓库架构分层,确定数据模型、主题、维度、粒度以及维度表事实表等
    • (4)制定各项规范,包括命名规范、字段规范、编码规范等;
    • (5)ETL作业开发和测试,以及数据质量检查;
    • (6)数据监控,数仓维护,模型优化。
    7.ETL流程应该有哪些?

    优化相关

    1.MaxCompute SQL中用到哪些优化?

    ​ 首先优化SQL的过程,实际上就是要尽可能减少IO读取,尽可能减少计算资源的使用,尽可能减少SQL复杂度,尽可能提升运行速度。

    • 建分区表,但建议分区层数不超过3层,后续查询时为了避免全表扫描需要分区裁剪,分区值尽量常量化,避免不可确定值;插入数据时尽量采用写入静态分区的方式,优化数据存储,如果用动态分区,会生成较多的小文件,增加系统负担。
    • 只select有效列,并用limit限制返回的条数。
    • 读取相同源表时可以合并成一条sql,系统会优化只读取一次。
    • mapjoin优化
    • 将full outer join 改为left outer join + union all 并对小表使用上mapjoin
    • 尽可能保证表达式两边的数据类型一致,如果发生隐式转换容易造成精度问题,比如string和bigint都转成double来相等比较,悲观情况下,可能触发数据倾斜。这时要cast显式转换一下
    • 少用distinct,容易触发数据倾斜,count(distinct)处理的时间会很长可以转换成count()+ group by
    • 多个表join时,join顺序很重要,优先选择join结果输出小的表先关联,能有效减少中间数据量,节省IO和计算资源。
    • 尽量使用内置的UDF函数和窗口函数,内置UDF在实现做了很多优化,运行块,省资源,窗口函数本身能处理很多复杂问题。
    • 尽量避免Order by,order by会触发全局排序,只能单点运行,效率低,如果业务允许,可以改成distribute by + sort by
    2.MaxCompute SQL介绍以及与通用数据库的区别?

    ​ MaxCompute SQL适用于海量数据,实时性要求不高的场合,MaxCompute 作业提交后会有几十秒到数分钟不等的排队调度;采用的是类似与SQL的语法,可以看作是标准SQL的子集,但也有不同点,比如没有事务,主键约束,索引等。

    ​ 有Bigint,double,String,datetime,Boolean,decimal类型。

    ​ 可以设置分区表,还可以给表指定生命周期LifeCycle

    ​ 具体区别如下:

    • 1.MaxCompute表不⽀持主键、索引和字段约束;
    • 2.MaxCompute表不⽀持UPDATE语句和DELECT语句,只能DROP 整个表或者某一分区数据;
    • 3.MaxCompute表创建表时不允许指定默认值,可以指定生命周期,周期结束后自动清除数据;
    • 4.SELECT语句输出的数据⾏数是受限制的,最⼤为10000条;
    • 5.MaxCompute 不支持主键,索引,不支持MINUS操作,MaxCompute的where子句也不支持between条件查询。
    • 6.MaxCompute把sql的关键字做为保留字,对列,表或是分区命名时不能直接使用保留字作命名。
    • 7.插入语句有insert into | overwrite into,overwrite into写入前会清空表数据;
    • 8.可以直接在select中使用mapjoin,所有小表占用的内存总和不得超过512MB,在官方文档中说mapjoin最多支持6张小表,但工作中我们是规定不能超过8张小表,因为有些表真的容量不大。
    • 9.MaxCompute SQL不支持顶级的两个查询结果合并,要改写为一个子查询的形式,也就是一个union all连接的语句,外面必须套一层select * from。
    • 10.MaxCompute也有内置函数,和大部分数据库的用法差不多,如果忘记可以直接查看官方文档。
      • MaxCompute常用到的函数:dateadd函数对日期加减法,datediff计算两个日期差值,getdate获取系统日期,cast转换目标数据类型, coalesce函数返回列表中第一个非空的值,case when;decode实现if-then-else分支选择的功能,concat连接所有字符串,instr函数计算子串在字符串中的位置,length函数,MD5函数计算输入字符串的md5值(常用作新加的主键),substr函数,to_char函数,to_date函数,lastday函数返回月的最后一天,lag窗口函数,row_number窗口函数计算行号从1开始,还有常用聚合函数等

    其它细微的区别用法详见官方文档。

    MaxCompute SQL

    1.MaxCompute SQL中用到哪些优化?

    ​ 首先优化SQL的过程,实际上就是要尽可能减少IO读取,尽可能减少计算资源的使用,尽可能减少SQL复杂度,尽可能提升运行速度。

    • (1)建分区表,但建议分区层数不超过3层,后续查询时为了避免全表扫描需要分区裁剪,分区值尽量常量化,避免不可确定值;插入数据时尽量采用写入静态分区的方式,优化数据存储,提高运行效率;如果用动态分区,底层来说会生成较多的小文件和多个mapreduce任务,增加系统负担。
    • (2)只select有效列,并用limit限制返回的条数。考虑这两种情况:(1)有些事实表的字段很多,多到有四五十个字段,这种表实际是可能存在的,比如企业报税的申报表,那么select * from整张表的所有字段时,数据量一大就会消耗更多查询时间;(2)第二种情况是假设事实表中存有某个复杂格式的字段,比如json格式,那么在select * from时也会耗时严重,因此select有效列是较好的习惯。
    • (3)mapjoin优化,mapjoin的原理简单说就是先将小表加载到内存中,后续大表与内存中的小表直接计算(底层是大表与内存中的小表的计算在map阶段直接完成,避免了reduce阶段的计算耗时)
    • (4)避免一些消耗资源的操作,比如:
      • 少用distinct,容易触发数据倾斜
      • count(distinct)处理的时间会很长可以转换成count()+ group by。因为如果原先只用count(distinct)来处理表的数据,只会开启一个reduce任务来完成所有的计算,而改成count/sum + group by后,除了count/sum会开启一个reduce计算之外,group by也会单独开启另一个reduce来计算,因此数据量大时可以明显提升查询速度。
      • 尽量避免Order by,order by会触发全局排序,只能单点运行,效率低,如果业务允许,可以改成distribute by + sort by
      • 将full outer join 改为left outer join + union all 并对小表使用上mapjoin。
      • 多个表join时,join顺序很重要,优先选择join结果输出小的表先关联,能有效减少中间数据量,节省IO和计算资源。
      • 读取相同源表时可以合并成一条sql,系统会优化只读取一次。
    • (5)尽量使用内置的UDF函数和窗口函数,内置UDF在实现时做了很多优化,运行快,省资源,窗口函数本身能处理很多复杂问题。
    • (6)尽可能保证表达式两边的数据类型一致,如果发生隐式转换容易造成精度问题,比如string和bigint都转成double来相等比较,悲观情况下,可能触发数据倾斜。这时要cast显式转换一下
    工作中还用到的:
    - 数据量达到千万级别的,尽量固化分区,不在查询sql里面进行动态分区,减少资源使用
    - sql行数较长的,尽量拆分成工作流任务,可以优化性能和排查问题的难易度。
    - 维度表要放到mapjoin里,加大资源利用率
    - 数据倾斜较高的表,先落地成临时表
    - 每日全量推送任务的,如果表级数据量较高的,分析是否可以改成增量模式。
    
     
     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2.MaxCompute SQL介绍以及与通用数据库的区别?

    ​ MaxCompute SQL适用于海量数据,实时性要求不高的场合,MaxCompute 作业提交后会有几十秒到数分钟不等的排队调度;采用的是类似与SQL的语法,可以看作是标准SQL的子集,但也有不同点,比如没有事务,主键约束,索引等。

    ​ 有Bigint,double,String,datetime,Boolean,decimal类型。

    ​ 可以设置分区表,还可以给表指定生命周期LifeCycle。

    ​ 具体区别如下:

    • 1.MaxCompute表不⽀持主键、索引和字段约束;
    • 2.最明显的区别是,MaxCompute表不⽀持UPDATE语句和DELECT语句(不支持更新操作),只能DROP 整个表或者某一分区数据,然后用INSERT OVERWRITE/INSERT INTO写入数据。
    • 3.MaxCompute表创建表时不允许指定默认值,可以指定生命周期,周期结束后自动清楚数据;
    • 4.SELECT语句输出的数据⾏数是受限制的,最⼤为10000条;
    • 5.MaxCompute 不支持MINUS差集操作,如果需要做差集操作可以用LEFT OUTER JOIN 然后取右表关联为空的数据。MaxCompute的where子句也不支持between条件查询。
    • 6.MaxCompute把sql的关键子做为保留字,对列,表或是分区命名时不能直接使用保留字作命名。
    • 7.插入语句有insert into | overwrite into,overwrite into写入前会清空表数据;
    • 8.可以直接在select中使用mapjoin,所有小表占用的内存总和不得超过512MB,在官方文档中说mapjoin最多支持6张小表,但工作中我们是规定不能超过8张小表,因为有些表真的容量不大。
    • 9.MaxCompute SQL不支持顶级的两个查询结果合并,要改写为一个子查询的形式,也就是一个union all连接的语句,外面必须套一层select * from加别名。
    • 10.MaxCompute也有内置函数,和大部分数据库的用法差不多,如果忘记可以直接查看官方文档或者MaxCompute的IDE也可以直接搜索。
      • MaxCompute常用到的函数:dateadd函数对日期加减法,datediff计算两个日期差值,getdate获取系统日期,cast转换目标数据类型, coalesce函数返回列表中第一个非空的值,case when;decode实现if-then-else分支选择的功能,concat连接所有字符串,instr函数计算子串在字符串中的位置,length函数,MD5函数计算输入字符串的md5值(常用作新加的主键),substr函数,to_char函数,to_date函数,lastday函数返回月的最后一天,lag窗口函数,row_number窗口函数计算行号从1开始,还有常用聚合函数等

    其它细微的区别用法详见官方文档。

    3.MaxCompute的其他细节:
    • MaxCompute不支持删除列的。

    • 参与Union All运算的所有列的数据类型和列个数、名称必须完全一致。

    • 数据类型只能是bigint、double、boolean、datetime和string;

    • lifecycle建表时指明此表的生命周期,但create table like时并不会复制源表的生命周期;

    • create table … as select …语句创建的表不会复制分区属性,而是把源表的分区键作为目标表的一般列处理;如果希望和源表有相同表结构,建议使用create table … like …,然后再手动插入数据。

    • 对于设置了生命周期的表,如果是非分区表,那么会从最后一次被修改的时间开始计算周期,周期时间到将会被MaxCompute自动回收,如果有数据更新,那么周期会重新刷新时间;如果是分区表,则细分到某个分区是否有被改动过,回收也只是针对某一个长时间为改动过的分区数据。

    • 删除分区:ALTER TABLE … DROP [IF NOT EXISTS] PARTITION …;

      添加列:ALTER TABLE … ADD COLUMNS();

      修改列名:ALTER TABLE … CHANGE COLUMN…RENAME TO …

      修改分区值:ALTER TABLE … PARTITION(分区=分区值) RENAME TO PARTITION(分区=分区值);

      修改表的注释:ALTER TABLE…SET COMMENT ‘’;

      修改表的生命周期:ALTER TABLE …SET LIFECYCLE = ‘’;

      清空非分区表的数据:TRUNCATE TABLE ;如果是分区表,需要ALTER TABLE … DROP PARTITION先删除分区数据再TRUNCATE

      修改列、分区的注释:ALTER TABLE … CHANGE COLUMN 列名 COMMENT ‘’;

    4.MaxCompute中的类型转换
    • MaxCompute中支持显示转换cast和隐式转换。

    • 对于显示转换过程中,会发生如下问题:

      • cast将double类型转换成bigint类型时,小数部分会被截断;
      • 满足double类型的string类型转为bigint类型时,会先将string转为double,然后再转为bigint,期间小数部分也会被截断。
    • String类型和Datetime类型之间的转换

      • MaxCompute支持两者的相互转换,但有一个注意点是各个单位的值域中,如果首位为0是不能忽略的,比如:cast(‘2020-1-1 12:12:!2’ as datatime)中的一月份没有写0就会报错。
    • 由于double存在精度差,所以不能直接对两个double类型的数值用=号判断相等,可以在相减后取绝对值的方式判断,当绝对值足够小时可以说明两数相等。

      abs(0.9999999999 - 1.0000000000) < 0.000000001
      
         
         
      • 1
    • String类型在参与运算前会进行隐式类型转换到double类型

    • bigint和double类型在计算时,bigint会隐式转换为double再计算,返回结果也是double

    • 位运算符不支持隐式转换,同时只允许bigint类型。逻辑运算符也不支持隐式转换,只允许boolean类型。

    5.MaxCompute中的mapjoin使用限制
    • left outer join的左表必须是大表;right outer join的右表必须是大表,inner join左右都可以是大表,full outer join不能使用mapjoin
    • mapjoin支持小表为子查询,使用mapjoin需要引用小表或者子查询时,需要引用别名
    • 在mapjoin中,可以使用不等值连接或者使用or连接多个条件
    • 最多指定8张小表(看新旧版本),所有小表占用的内存总和不能超过512M,否则报语法错误。
    • 多个表join时,最左边的两张表不能同时时mapjoin的表。

    - 学习参考

    《开课吧-大数据开发高级工程师一期》课程

    文章知识点与官方知识档案匹配,可进一步学习相关知识
    MySQL入门技能树数据库组成 57744 人正在系统学习中
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐