Hive总结
2023-03-27 15:23:40 2 举报
AI智能生成
对于hive的详细总结,结合本人实际生产经验,有需要拿走
作者其他创作
大纲/内容
hive架构图
hive基本概念
hive简介
hive的前生属于Facebook,用于解决海量结构化数据的统计分析,现在属于Apache软件基金会。Hive是一个构建在Hadoop之上的数据分析工具<br>(hive没有存储数据的能力,只有使用数据的能力)
为什么使用
操作接口采用类似于sql的语法,提供快速开发的能力<br>免去了写mapreduce的过程,减少开发人员的学习成本<br>功能扩展方便
hive优缺点
优点:<br> 1、操作接口采用类似sql的语法,提供快速开发的能力(简单、容易上手)<br> 2、免去了写mapreduce的过程,减少开发人员的学习成本<br> 3、hive的执行延迟比较高,因此hive常用于离线数据分析,对实时性要求不高的场合<br> 4、hive的优势在于处理大数据,对于处理小数据没有优势,因为hive的执行延迟比较高<br> 5、hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数<br> 6、集群可自由拓展并且具有良好的容错性,节点出现问题sql仍可完成执行<br>缺点:<br> 1、hive的hql表达能力有限,当逻辑需求特别复杂的时候,还是需要借助mapreduce<br> 2、hive操作默认基于mapreduce引擎,而mapreduce引擎与其它的引擎相比,特点就是慢,延迟高、不适合交互查询,所以hive也有这个缺点<br> 3、hive自动生成的mapreduce作业,通常情况下不够智能化<br> 4、hive调优比较困难,粒度较粗
注意
hive在0.14版本之后开始支持事务,前提是文件格式必须为orc格式,同时必须分桶,还必须显式声明transactional=true
hive架构
client
hive允许client连接的方式有三个:hive shell、jdbc/odbc、webui。jdbc/odbc访问中间件thrift软件框架,跨语言服务开发。DDL\DQL\DML
metastore
元数据,数据的数据。元数据包括表名、表结构信息、所属表的数据库(默认是default库)、表的拥有者(权限信息)、列/分区字段、表的类型等等<br>元数据的存放一般需要借助于其它的数据载体(derby或mysql),默认存放在自带的derby数据库,推荐使用mysql进行存储。<br>元数据服务的作用是:客户端连接metastore服务,metastore服务再去连接mysql数据库来存储元数据,有了metastore服务,就可以有多个客户端同时连接,<br>而且这些客户端不需要指导mysql数据库的用户名和密码,只需要连接metastore服务即可。
driver
解析器(Parser)
将hql语句解析成抽象语法树
hdfs
hive的数据存储在hdfs中,计算由mapreduce完成。hdfs和mapreduce是源码级别上的整合,两者结合最佳。解释器、编译器、优化器<br>完成hql查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。
内外部表
内部表
所谓内部表即hive管理的表,hive内部表的管理既包含逻辑以及语法上的,也包含实际物理意义上的,即创建hive内部表时,数据将真实存在于表所在的目录内
外部表
外部表仅仅只是在逻辑和语法意义上的,即新建表仅仅时指向一个外部目录而已。同时,删除时也并不会物理删除外部目录,而仅仅是将引用和定义删除。<br>一般情况下,在企业内部都是使用外部表的,因为会有多人操作数据仓库,可能回产生数据表误删除操作,为了数据安全性,通常会使用外部表,以达到数据共享
hive分区/分桶
hive分区
使用分区技术,可以避免hive全表扫描,提升查询效率;同时能够减少数据冗余进而提高特定查询分析的效率。<br>注意,在逻辑上分区表与未分区表没有区别,在物理上分区表会将数据按照分区键的键值存储在表目录的子目录中。<br>使用分区表时,尽量利用分区字段进行查询,如果不使用分区字段查询,就会全部扫描,这样就失去了分区的意义<br>静态/动态分区:前者是我们手动指定的,后者是通过数据来判断分区的。详细来说,静态分区的列是在编译时期通过用户传递来决定的;<br>动态分区只有在sql执行时才能决定。
hive分桶
分桶是将数据分解为更为容易管理的若干部分的另一种技术,也就是更为细粒度的数据范围划分,将数据按照字段划分到多个文件中去<br>hive采用队列值哈希,然后除以桶的个数求余的方式决定该条记录要存放在哪个桶中。<br>分桶优势:方便抽样,使抽样更加高效<br> 提高join查询效率,可以减少join的数据量
hive基础函数
in与exists
in相当于使用or的多个等值查询,效率不高,用于一些少量定值判断上,如果有子查询,确定给定的值是都与子查询或列表中的值相匹配。<br>in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡儿积,然后按照条件进行筛选,所以相对内表比较小的时候,in的速度较快<br>而exists则是检测行的存在,循环遍历外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。
全局排序
全局排序也就是order by,语法类似sql语法的order by<br>底层实现:全局排序是在一个reduce中进行排序的
局部排序
对于大规模的数据集order by的效率非常低。在很多情况下,并不需要全局排序,此时可以使用sort by。sort by为每个reducer产生一个排序文件,只在每个reducer内部进行排序
分区排序
distribute by子句可以控制某个特定行应该到哪个reducer,为后续的聚集操作做准备,其算法是hash散列
组合排序
cluster by 除了具有分区排序的功能之外,还兼具了sort by 的功能,但是排序只能是升序排序,不能指定排序规则为asc/desc
hive高级查询
一行变多行
EXPLODE()可以将hive一行中复杂的Array或者Map结构拆分成多行,配合split函数可以将某个列的数据转为数组
多行变一行
collect_set()和collect_list()可以将多行数据转换成一行数据,区别就是list的元素可重复而set的元素是去重的
URL解析
侧视图lateral view配合parse_url_tuple函数可以实现url字段的一列变多列
hive窗口函数
窗口函数语法
窗口函数指的就是over()函数,其窗口是由一个over子句定义的多行记录。窗口函数一般分为三类:聚合型窗口函数和分析型窗口函数以及取值型窗口函数。<br>partition by:后跟分组的字段,划分的范围被称为窗口<br>order by:决定窗口范围内数据的排序方式<br>current row:当前行<br>preceding:向当前行之前移动<br>following:向当前行以后移动<br>unbounded:起点或终点(一般结合preceding,following使用)
移动窗口(滑动窗口)
列的顺序取前 N 行或后 N 行进行计算(当前行也参与计算)。<br>ROWS 2 PRECEDING :窗口从当前行的前两行开始计算,计算到当前行;<br>ROWS BETWEEN 2 PRECEDING AND CURRENT ROW :等同于上一句;<br>ROWS BETWEEN CURRENT ROW AND 2 FOLLOWING :窗口从当前行开始计算,计算到当前行的后两行;<br>ROWS BETWEEN 2 PRECEDING AND 1 FOLLOWING :窗口从当前行的前两行开始计算,计算到当前行的下一<br>行,当前行也参与计算;<br>ROWS UNBOUNDED PRECEDING :窗口从第一行(起点)计算到当前行;<br>ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW :等同于上一句;<br>ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING :窗口从当前行计算到最后一行(终点);<br>ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING :窗口从第一行(起点)计算到当前行下一行;<br>ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING :窗口从第一行(起点)计算到最后一<br>行(终点)。<br>RANGE :RANGE 后定义窗口从哪里开始(当前行也参与计算),与 BETWEEN 搭配可以表示范围。如果省略<br>BETWEEN 仅指定一个端点,那么将该端点视为起点,终点默认为当前行。RANGE 会根据 ORDER BY 子句排序后,按<br>分组后排序列的值的整数区间取前 N 行或后 N 行进行计算(相同排序值的行都会被算进来,当前行也参与计算)。<br>RANGE 的窗口范围子句语法与 ROWS 一模一样,唯一的区别就在于 RANGE 会根据 ORDER BY 子句排序后,按分组<br>后排序列的值的整数区间取前 N 行或后 N 行进行计算(相同排序值的行都会被算进来,当前行也参与计算)。<br>整数区间解释:如果窗口范围子句为 RANGE BETWEEN 2 PRECEDING AND CURRENT ROW ,假设排序列的值为<br>1 2 3 4 5 7 8 10<br><br>当 ORDER BY 缺少窗口范围子句时,窗口范围子句默认为: RANGE BETWEEN UNBOUNDED PRECEDING AND<br>CURRENT ROW 。<br>当 ORDER BY 和窗口范围子句都缺失时,窗口范围子句默认为: ROW BETWEEN UNBOUNDED PRECEDING AND<br>UNBOUNDED FOLLOWING 。<br>
分析型窗口函数
rank():间断,相同值同序号,例如1、2、2、2、5<br>dense_rank():不间断,相同值同序号,例如1、2、2、2、3<br>row_number():不间断,序号不重复,例如1、2、3、4、5(2、3可能是相同的值)<br>percent_rank():计算小雨当前行的值在所有行中的占比,类似百分比排名。可以用来计算超过了百分之多少的人。计算某个窗口或分区中某个值的累积分布<br>cum_dist():计算小雨等于当前行的值在所有行中的占比<br>ntile(n):如果把数据按行数分为n份,那么该行所属的分数是第几份。注意:n必须为int类型
取值型窗口函数
LAG(COL, N, DEFAULT_VAL) :往前第 N 行数据,没有数据的话用 DEFAULT_VAL 代替。<br>LEAD(COL, N, DEFAULT_VAL) :往后第 N 行数据,没有数据的话用 DEFAULT_VAL 代替。<br>FIRST_VALUE(EXPR) :分组内第一个值,但是不是真正意义上的第一个或最后一个,而是截至到当前行的第一个或<br>最后一个。<br>LAST_VALUE(EXPR) :分组内最后一个值,但是不是真正意义上的第一个或最后一个,而是截至到当前行的第一个<br>或最后一个。
hive自定义函数
udf
普通函数,一进一出,比如upper,lower<br><br>
udaf
聚合函数,多进一出,比如count/max/min
udtf
表生成函数,一进多出,比如lateral view explode
自定义udf
实现udf的方式有两种,第一种是比较简单的形式,继承udf类通过evaluate方法实现,目前已过时。<br>第二种是继承genericUDF重写initialize方法、evaluate方法、getDisplayString方法实现。
自定义udaf
实现 UDAF 的方式有两种,第一种是比较简单的形式,先继承 UDAF 类,然后使用静态内部类实现 UDAFEvaluator 接<br>口,目前已过时。第二种是先继承 AbstractGenericUDAFResolver 类重写 getEvaluator 方法,然后使用静态内部类实现<br>GenericUDAFEvaluator 接口。这里主要讲第二种。
自定义udtf
UDTF(User Defined Table Generating Function):表生成函数,一进多出,用于处理单行数据,并生成多个数据行。<br> 实现 UDF 需要继承的 GenericUDTF,然后重写父类的三个抽象方法,输出后有几列,在 initialize 中定义,主要处理逻<br>辑在 process 中实现。
hive压缩
概述
压缩技术能够有效减少存储系统的读写字节数,提高网络带宽和磁盘空间的效率。
压缩方式比较
hive存储
存储方式
行式存储
查询满足条件的一整行数据的时,只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更<br>快。<br>传统的关系型数据库,如 Oracle、DB2、MySQL、SQL SERVER 等都是采用行式存储,在基于行式存储的数据库中,数<br>据是按照行数据为基础逻辑存储单元进行存储的,一行中的数据在存储介质中以连续存储形式存在。<br>Text File 和 Sequence File 的存储格式都是基于行存储的。<br>这种存储格式比较方便进行 INSERT/UPDATE 操作,不足之处就是如果查询只涉及某几个列,它会把整行数据都读取出<br>来,不能跳过不必要的列读取。当然数据比较少,一般没啥问题,如果数据量比较大就比较影响性能,还有就是由于<br>每一行中,列的数据类型不一致,导致不容易获得一个极高的压缩比,也就是空间利用率不高。
列式存储
查询时,只有涉及到的列才会被查询,不会把所有列都查询出来,即可以跳过不必要的列查询,在查询只需要少数几<br>个字段的时候,能大大减少读取的数据量;因为每一列的数据都是存储在一起的,每个字段的数据类型一定是相同<br>的,列式存储可以针对性的设计更好的设计压缩算法,高效的压缩率,不仅节省储存空间也节省计算内存和 CPU。<br>INSERT/UPDATE 很麻烦或者不方便,不适合扫描小量的数据。<br>列式存储相对于行式存储来说,是新兴的 Hbase、HPVertica、EMCGreenplum 等分布式数据库均采用的存储方式。在<br>基于列式存储的数据库中, 数据是按照列为基础逻辑存储单元进行存储的,一列中的数据在存储介质中以连续存储形<br>式存在。
存储格式
textFile
默认格式,存储方式为行式存储,数据不做压缩,磁盘开销大,数据解析开销大<br>仅在需要从hadoop中直接提取数据,或者直接从文件中加载大量数据的情况下,才建议使用纯文本格式或csv
sequence file
一种支持二进制格式的存储格式,存储方式为行存储,其具有使用方便、可分割、可压缩的特点。一般建议使用block压缩<br>通常把它作为中间数据存储格式,例如:将大量小文件合并放入一个sequence file中 。
orc file
orc代表“优化行列”,它以比rc更为优化的方式存储数据,提供了一种非常有效的方式来存储关系数据,然后存储rc文件。orc将原始数据的大小最多减少75%,数据处理速度打打提高
parquet file
一种列式存储的结构,基于列的二进制存储格式,可以存储嵌套的数据结构。当指定<br>要使用列进行操作时,磁盘输入/输出操效率很高。Parquet 与 Cloudera Impala 兼容很好,并做了大量优化。Parquet 还支<br>持块压缩。与 RC 和 ORC 文件不同的是,Parquet Serdes 支持有限的 Schema 扩展。在 Parquet 中,可以在结构的末尾添加<br>新列。其列名必须小写,否则hive无法读取
0 条评论
下一页