hive主要知识点

1、数据仓库

数据仓库是一个面向主题的、集成的、随时间变化的、但信息本身相对稳定的数据集合,用于对管理决策过程的支持。

2、数据库和数据仓库

数据库:是一种逻辑概念,用来存放数据的仓库。通过数据库软件来实现。数据库由许多表组成,表是二维的,一张表里面可以有很多字段,数据库的表,在与能够用二维表现多维关系。
数据仓库:是数据库概念的升级。从逻辑上理解,数据库和数据仓库没有区别,都是通过数据库软件实现的存放数据的地方,只不过从数据量来说,数据仓库要比数据库更庞大得多。数据仓库主要用于数据挖掘和数据分析,辅助领导做决策。
数据库与数据仓库的区别实际讲的是OLTP与OLAP的区别。
对比:
操作型处理,叫联机事务处理OLTP(On-Line Transaction Processing,),也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理。
分析型处理,叫联机分析处理OLAP(On-Line Analytical Processing)一般针对某些主题的历史数据进行分析,支持管理决策。
Hive基于Hadoop的一个数据分析工具,而且是将结构化的数据文件映射为一张数据库表,它提供的是类SQL查询功能,HQL语句转换为MapReduce的任务,然后来进行数据访问。
Hive和数据库比较
Hive 和数据库除了拥有类似的查询语言,再无类似之处。
1)数据存储位置
Hive 存储在 HDFS 。数据库将数据保存在块设备或者本地文件系统中。
2)数据更新
Hive中不建议对数据的改写。而数据库中的数据通常是需要经常进行修改的,
3)执行延迟
Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
4)数据规模
Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。

3、数据仓库和数据集市的区别

数仓是面向整个集团组织的数据,数据集市是单个部门使用的,数据集市是数据仓库的子集,是一个主题域。

4、数仓的分层架构

ODS层:贴源层,与业务库保持一致,不做任何处理
DWD层(TD中P层):明细层,对数据进行规范话化,转换清洗。
DWS层(TD中CDM层):对数据按维度进行汇总,降低业务需求
ADS层:应用层,面向业务需求开发。
分层的好处:
清晰数据结构
数据血缘追踪
减少重复开发
把复杂问题简单化

5、Hive架构

什么是hive:Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射成一张表,并提供类SQL查询功能;其本质是将HQL转化成MapReduce程序。

在这里插入图片描述

6、DDL DML DCL

DDL(data definition language)数据库定义语言:
其实就是我们在创建表的时候用到的一些sql,比如说:CREATE、ALTER、DROP等。DDL主要是用在定义或改变表的结构,数据类型,表之间的链接和约束等初始化工作上
DML(data manipulation language)数据操纵语言:
就是我们最经常用到的 SELECT、UPDATE、INSERT、DELETE。 主要用来对数据库的数据进行一些操作。
DCL(Data Control Language)数据库控制语言:
是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。这个比较少用到。

7、Hive数据类型

在这里插入图片描述
在这里插入图片描述

类型转化
Hive 的原子数据类型是可以进行隐式转换的,类似于 Java 的类型转换,例如某表达式使用 INT 类型,TINYINT 会自动转换为 INT 类型,但是 Hive 不会进行反向转化,例如,
某表达式使用 TINYINT 类型,INT 不会自动转换为 TINYINT 类型,它会返回错误,除非使用 CAST 操作。

1.隐式类型转换规则如下
(1)任何整数类型都可以隐式地转换为一个范围更广的类型,如 TINYINT 可以转换成 INT,INT 可以转换成 BIGINT。
(2)所有整数类型、FLOAT 和 STRING 类型都可以隐式地转换成 DOUBLE。
(3)TINYINT、SMALLINT、INT 都可以转换为 FLOAT。
(4)BOOLEAN 类型不可以转换为任何其它的类型。
2.可以使用 CAST 操作显示进行数据类型转换

8、Hive内部表和外部表

Hive创建内部表时,会将数据移动到数据仓库指向的路径。hive默认创建的是内部表。
创建外部表时,仅记录数据所在的路径,不对数据的位置做任何改变。
在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。需要注意的是传统数据库对表数据验证是写时模式,而Hive在load时是不检查数据是否符合schema的,Hive遵循的是读时模式,只有在读的时候Hive才检查解析具体的数据字段。
Load data会转移数据
下面是几条原则 :
1.在大部分场景下,两种表的应用没有太大的区别。
2.数据场景简单, 几乎都是在Hive中的流转, 可以优先选用内部表。
3.需要对数据内容和元数据进行紧凑的管理, 建议内部表。
比如负责计算过程中用到的临时表, 数据内容随用随删, 而不希望关注底层文件。
4.数据处理场景较多,复杂, 建议采用外部表。
比如需要用Spark, Mapreduce等处理复杂的数据, 然后用Hive 做后续处理的; 需要处理非结构化日志数据的情况。
5.需要对数据和元数据分开管理的场景, 对数据安全性要求更高的场景, 建议采用外部表。

9、索引、分区和分桶

Hive的索引目的是提高Hive表指定列的查询速度。
没有索引时,类似’WHERE tab1.col1 = 10’ 的查询,Hive会加载整张表或分区,然后处理所有的rows,
但是如果在字段col1上面存在索引时,那么只会加载和处理文件的一部分。
与其他传统数据库一样,增加索引在提升查询速度时,会消耗额外资源去创建索引表和需要更多的磁盘空间存储索引。
分区:
是指按照数据表的某列或某些列分为多个区,区从形式上可以理解为文件夹,
我们可以按照日期对数据表进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。
创建分区表的时候,要通过关键字 partitioned by (name string)声明该表是分区表
向分区表导入数据的时候,要通过关键字partition(name=“jack”)显示声明数据要导入到表的哪个分区,这里表示要将数据导入到分区为name=jack的分区。
分桶:
分桶是相对分区进行更细粒度的划分。分桶将整个数据内容安装某列属性值得hash值进行区分,如要安装name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。
注意:第一,分桶之前要执行命令hive.enforce.bucketiong=true;
第二,要使用关键字clustered by 指定分区依据的列名,还要指定分为多少桶,这里指定分为3桶。
第三,与分区不同的是,分区依据的不是真实数据表文件中的列,而是我们指定的伪列,但是分桶是依据数据表中真实的列而不是伪列。所以在指定分区依据的列的时候要指定列的类型,因为在数据表文件中不存在这个列,相当于新建一个列。而分桶依据的是表中已经存在的列,这个列的数据类型显然是已知的,所以不需要指定列的类型。
索引和分区最大的区别就是索引不分割数据库,分区分割数据库。
索引其实就是拿额外的存储空间换查询时间,但分区已经将整个大数据库按照分区列拆分成多个小数据库了。
分区和分桶最大的区别就是分桶随机分割数据库,分区是非随机分割数据库。
因为分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。
其次两者的另一个区别就是分桶是对应不同的文件(细粒度),分区是对应不同的文件夹(粗粒度)。
注意:普通表(外部表、内部表)、分区表这三个都是对应HDFS上的目录,桶表对应是目录里的文件

10、Order by、Sort by、Distribute by、Cluster by

Order by 查询的结果做一次全局排序
Sort by 在每个reducer端都会做排序,也就是说保证了局部有序
Distribute by和sort by一起使用,distribute by必须要写在sort by之前。
Cluster by的功能就是distribute by和sort by相结合,cluster by指定的列只能是降序,不能指定asc和desc。

11、窗口函数

RANK() 排序相同时会重复,总数不会变
DENSE_RANK() 排序相同时会重复,总数会减少
ROW_NUMBER() 会根据顺序计算
1) OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化
2)CURRENT ROW:当前行
3)n PRECEDING:往前n行数据
4) n FOLLOWING:往后n行数据
5)UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点
6) LAG(col,n):往前第n行数据
7)LEAD(col,n):往后第n行数据
8) NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。

高级聚合函数
grouping sets 根据感兴趣的维度组合进行聚合
cube 分别按照不同维度进行聚合
rollup 函数是cube的子集,以最左侧维度为主,按照顺序依次进行聚合.

12、自定义函数

Hive自定义函数包括三种UDF、UDAF、UDTF
UDF(User-Defined-Function) 一进一出
UDAF(User- Defined Aggregation Funcation) 聚集函数,多进一出。Count/max/min
UDTF(User-Defined Table-Generating Functions) 一进多出,如lateral view explore)
使用方式 :在HIVE会话中add 自定义函数的jar文件,然后创建function继而使用函数。
用UDF函数解析公共字段;用UDTF函数解析事件字段。
自定义UDF:继承UDF,重写evaluate方法
自定义UDTF:继承自GenericUDTF,重写3个方法:initialize(自定义输出的列名和类型),process(将结果返回forward(result)),close
为什么要自定义UDF/UDTF,因为自定义函数,可以自己埋点Log打印日志,出错或者数据异常,方便调试.

13、动态分区

a. 静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。
b. 详细来说,静态分区的列实在编译时期,通过用户传递来决定的;动态分区只有在 SQL 执行时才能决定。
c. 动态分区是基于查询参数的位置去推断分区的名称,从而建立分区

14、Hive行转列函数

concat_ws(sep, collect_set(col1)) :同组不同行合并成一列,以sep分隔符分隔。collect_set在无重复的情况下也可以collect_list()代替。collect_set()去重,collect_list()不去重
lateral view explode(split(col1,‘,’)) :同组同列的数据拆分成多行,以sep分隔符区分。
collect_set和collect_list区别:
它们都是将分组中的某列转为一个数组返回,不同的是collect_list不去重而collect_set去重。

15、Hive压缩格式

常用的主要由gzip,bzip2,snappy,lzo这几种.
在压缩速度上:snappy>>lzo>gzip>bzip2
在解压速度上: snappy>>lzo>gzip>bzip2
输入压缩:io.compression.codecs.xxxCodec(在core-site.xml中配置)
开启输出压缩:mapreduce.map.output.compress=false 默认值
使用map输出压缩类型:mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.BZip2Codec
reduce输出:mapreduce.output.fileoutputformat.compress=false(默认)
reduce输出压缩类型:mapreduce.output.fileoutputformat.compress=org.apache.hadoop.io.compress.BZip2Codec
输出使用的压缩类型:
mapreduce.output.fileoutputformat.compress.type=BLOCK;

开启hive中间传输压缩功能 hive.exec.compress.intermediate=true;
开启map输出阶段压缩可减少job中map和reduce的数据传输量
开启hive最终输出压缩功能:hive.exec.compress.output=true;

16、Hive的一些存储格式

TEXTFILE(行式存储),SEQUENCEFILE(行式存储),PARQUET(列式存储),ORC(列式存储)。
行式存储:1.行查询效率高。
2.列查询效率低。
3.数据压缩效率低。(因为一行中各列的数据类型有可能不行,会不停切换压缩格式)
列式存储:1.行查询效率低。
2.列查询效率高。
3.数据压缩效率高。
TEXTFILE:默认格式,数据不做压缩,磁盘开销大,数据解析开销大。结合gzip和bzip2使用。
ORC:每个ORC文件有一个或多个stripe组成,每个stripe有250mb大小。一个stripe由IndexData,RowData,StripFooter组成。indexData:某些列的索引数据;RowData:真正的数据存储;StripFooter:Stripe的元数据信息。
Parquet:是面向分析型业务的存储格式。是二进制存储的,不能直接读取,文件中包含文件的数据和元数据。
存储文件压缩对比:ORC>PARQUET>TEXTFILE
查询文件速度对比:ORC>TEXTFILE>PARQUET

17、Hive的调优

1.当一些单表数据量不大select * 查询时候,可以采取fetch抓取,查询不走mr。
set hive.fetch.task.conversion=more;(none为不适用)

2.当查询一些小数据集时候,可以开启本地模式,在单台机器上完成处理。
set hive.exec.mode.local.auto=true;

3.如果是小表关联大表,可以使用map join使数据在map阶段就开始join操作
set hive.auto.convert.join=true;
设置小表的阈值(大概在25M)
set hive.mapjoin.smalltable.filesize=25123456;

4.默认情况,map阶段同一个key的数据会分发给一个reduce,当一个key数据过大时候就容易发生数据倾斜。可以在map段做局部的聚合。
是否在map段进行聚合
set hive.map.aggr=true;
在map端进行聚合的条目数量
set hive.groupby.mapaggr.checkinterval=1000000
当发生数据倾斜时候是否进行负载均衡
set hive.groupby.skewindata=true;
当为true时,会生成两个mr job
第一个mr job中,map输出的数据会随机分布到reduce中,每个reduce做部分聚合工作,并输出结果。这样处理的结果是相同的group by key有可能被分发到不同的reduce中,从而达到负载均衡的目的。
第二个mr job在根据预处理的数据结果按照group by key分布到reduce中(这个过程可以保证同一个group by key 被分布到同一个reduce中),最后完成最终的聚合操作。

5.count(distinct)
因为同一个字段去重如果使用多个reduce达不到效果,但是如果一个reduce处理的数据量过大就导致job很难完成。所以可以先将字段进行group by 操作然后再使用count。

6.笛卡尔积
尽量避免join下不加on条件,或者无效的on条件。Hive只能使用一个reduce来处理笛卡尔积。

7.动态分区参数设置。
开启动态分区功能
set hive.exec.dynamic.partition=true;
开启非严格模式
set hive.exec.dynamic.partition.mode=nonstrict;
在所有MR节点上,最多允许创建分区个数
set hive.exec.max.dynamic.partitions=1000
在每一个MR节点上,最多创建最大的分区个数
set hive.exec.max.dynamic.partitions.pernode=1000
在每一个MR JOB中,最多可以创建HDFS文件的个数
set hive,.exec.max.created.files=100000
当有空分区生成时,是否产生异常
set hive.error.on.empty.partition=false

8.并行执行。HIVE查询会转化为一个或多个阶段,当这些阶段中没有依赖关系时候可以采用。
不过job中并行的多,会占用集群的资源。
set hive.exec.parallel=true;

9.严格模式。
set hive.mapred.mode=nonstrict;
set hive.mapred.mode=strict;
1.对于分区表,where的后面必须由指定的分区字段来作为过滤条件,否则不允许执行。
2.对使用了order by语句的,必须加上limit。
3.限制笛卡尔积的查询。

10.JVM重用
set hive.mapred.reuse.jvm.num.tasks=10;

18、小文件的解决方案

从源头解决
1.使用Sequencefile作为存储格式,不用textfile。
2.减少reduce的数量(可以通过参数控制)
3.少用动态分区,用时记得按distributed by分区
对于已有的小文件
1.使用hadoop archive命令把小文件进行归档。
2.重建表,建表时减少reduce数量。
3.通过参数进行调节,设置map/reduce端的相关参数
如下:
设置map输入合并小文件的相关参数
//每个Map最大输入大小(这个值决定了合并后文件的数量)
set mapred.max.split.size=256000000;
//一个节点上split的至少的大小(这个值决定了多个DataNode上的文件是否需要合并)
set mapred.min.split.size.per.node=100000000;
//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack=100000000;
//执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

设置map输出和reduce输出进行合并的相关参数:
//设置map端输出进行合并,默认为true
set hive.merge.mapfiles = true
//设置reduce端输出进行合并,默认为false
set hive.merge.mapredfiles = true
//设置合并文件的大小
set hive.merge.size.per.task = 25610001000
//当输出文件的平均大小小于该值时,启动一个独立的MapReduce任务进行文件 merge
set hive.merge.smallfiles.avgsize=16000000

19、hive数据倾斜如何解决

1)group by,hive.map.aggr=true 这个配置项代表是否在map端进行聚合
2)map和reduce优化 要增加map个数 ; 当出现小文件过多,需要合并小文件。可以通过set hive.merge.mapfiles=true来解决
3)当HiveQL中包含count(distinct)时,使用sum…group by代替
4)当遇到一个大表和一个小表进行join操作时,使用mapjoin 将小表加载到内存中
5)遇到需要进行join的但是关联字段有数据为空,给空值分配随机的key值

20、mapjoin的实现原理?

MapJoin通常用于一个很小的表和一个大表进行join的场景,具体小表有多小,由参数 hive.mapjoin.smalltable.filesize来决定,该参数表示小表的总大小,默认值为25000000字节,即25M.
把小表文件复制到每一个Map任务的本地,再让Map把文件读到内存中待用。
MapJoin顾名思义,就是在Map阶段进行表之间的连接。而不需要进入到Reduce阶段才进行连接
MapJoin的实现方法:
1)在Map-Reduce的驱动程序中使用静态方法DistributedCache.addCacheFile()增加要拷贝的小表文件,。JobTracker在作业启动之前会获取打这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。
2)在Map类的setup方法中使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值