Hive 原理
1. 用户提交查询等任务给Driver。
2. 编译器获得该用户的任务Plan。
3. 编译器Compiler根据用户任务去MetaStore中获取需要的Hive的元数据信息。
4. 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后将抽象语法树转换成查询块,将查询块转化为逻辑的查询计划,重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce), 最后选择最佳的策略。
5. 将最终的计划提交给Driver。
6. Driver将计划Plan转交给ExecutionEngine去执行,获取元数据信息,提交给JobTracker或者SourceManager执行该任务,任务会直接读取HDFS中文件进行相应的操作。
7. 获取执行的结果。
8. 取得并返回执行结果。
Mapreduce和hive的区别和联系
2、实战场景
先看这样一个场景. 每一个用户在登录到网站上的时候会带有一个ip地址,多次登录可能会有多个不同的ip地址.假设,我们已经有一个 用户->ip地址这样的一份数据.我们需要对此进行分析,得到一份来自相同ip的用户的关系表,数据格式类似
第1步 用udf取最频繁ip
我们先看一下原始数据的字段,是user_id,ips,我们再来看看ips内容的格式,我们执行Select * from iptable limit 100 但是我们可以通过打开一个hive.limit.optimize.enable=true来简化这个查询,当这个选项打开以后hive会读取hive.limit.row.max.size,hive.limit.optimize.limit.file的默认值来进行小数据量的计算。 我们要从用户->[ip地址] 这样的数据中得到一个用户使用最多的ip地址作为用户的最常用ip。这里我们会使用hive的自定义udf来完成这一步的工作。 这些都是一些比较通用的处理,如果有的时候我们要在字段上做一些特殊的逻辑就要自己动手写了.
@Description``(name = “freq``ips”, value = “find most frequence ips from all login ip”, extended = “”)``public` `class` `FindFreqIps ``extends` `UDF {`` ``public` `String evaluate(String content, ``int` `limit) {`` ``// 计算最常用ip的代码逻辑,并返回结果`` ``Return result;`` ``}``}
里面的逻辑主要就是找到前limit个最长使用的 Ip,我们看到我们的类需要继承自hive包中的UDF类,然后任意的定义输入类型和返回类型,但是方法的名字一定要叫evaluate,hive会使用 反射来得到这个方法的输入输出。当我们要在hive中使用它的时候,我们要首先把这个类打成jar包,然后让hive可以访问到。一般可以直接放在 hdfs上,然后使用
Add` `jar hdfs_path/myjar.jar;``Create` `temporary` `function` `FindFreqIps ``as` `‘FindFreqIps’``Select` `user_id, FindFreqIps(ips) ``as` `freqIps ``from` `tablexxx
另外还有一种是继承自genericUDF,这种方式可以自由的控制输入和返回类型处理,比起UDF来说更加的灵活些。但是我们这里普通的udf就足够了。
第2步 列转行,进行join
从第一步,我们得到了用户最常用的N个ip,我们这里假设值3个。然后我们要找到这些用户之间的关联,即相同的ip的关系。那么非常直接的方式,我们直接对用户的ip进行join,但是现在ip是3个连在一起字符串的形式,无法直接join。那么我们就先把ip都分解开。
Select` `user_id,ip ``from` `tablexxx``Lateral ``view` `explode(split(ips, “,”))``subview ``as` `ip
这样就会得到 user->ip的单条的记录。这里的这下要join就方便了,假设上面的结果表是singleIP我们 什么,报错了! 于是,我们就只能曲线救国了。 你会发现,执行了1次join,2次select使用的mr的步骤还是一步。一般总感觉嵌套了一次select以后也会对应的产生2次mr,难道是hive自己进行了优化吗?那么我们借助hive的分析工具来看看hive是如何执行的呢。 Hive会通过antlr来对输入的sql语句进行语法分析,产生一个执行计划。
第一部分是ABSTRACT SYNTAX
TREE抽象语法树这里面显示了hive把这个sql解析成什么样的各个token。
第二部分是STAGE DEPENDENCIES
一个hive的执行过程会包含多个stage,他们之间有互相依赖的关系。比如下面
Stage-1 is a root``stage` `Stage-0 depends on stages: Stage-1` `Stage-3 depends on``stages: Stage-0
这里的stage-1是root stage。而0依赖于1,3依赖于0。
第三个部分是STAGE PLANS, 就是每个stage中的具体执行的步骤。
在stage plans里面每一个stage和普通的hadoop程序一样会有map和reduce的过程。我们截取一段map过程的计划看下。
Stage: Stage-1`` ``Map Reduce`` ``Alias ->``Map Operator Tree:`` ``a`` ``TableScan`` ``alias``:``a`` ``Reduce``Output Operator`` ``key expressions:``expr``: ip``type``: string` ` ``sort` `order: +``Map-reduce partition columns:``expr``: ip``type``: string`` ``tag:``0`` ``value expressions:``expr``: user_id``type``: string
这里是对a表也就是SingleIP表的一个 map阶段的操作。Reduce output operator这里会显示使用ip作为key,自增排序,因为是string的所以是字典序的自增。Partition使用ip作为分发字段。tag指的是类似一个来源的概念,因为这里的join采用的是reduce join的方式,每一个从不同的map来的数据最后在reduce进行汇合,他们会被打上一个标记,代表他们的来源。然后就是value的内 容,user_id。
Reduce Operator Tree:` ` ``Join``Operator` ` ``condition``map:` `Inner Join 0 to 1` ` ``condition``expressions:` ` ``0``{VALUE._col0}` ` ``1``{VALUE._col0}` `handleSkewJoin: ``false` `outputColumnNames: _col0, _col2
这里显示一个join的操作。这里表示把0的内容加到1上。后面有一个handleSkewJoin,这个是hive的一个应对数据倾斜的一种处理方式,默认是关闭的,我们后面再来详细看。这里也可以用explain extended,输出的信息会更加详细。那么看了这个我们再比较一下我们之前的第二个查询计划,我们来看看加上了嵌套查询以后的执行计划有什么变化呢?会发现hive在reduce的执行计划里面会加上一段 在reduce最后输出之前,进行了一个过滤的操作,过滤的条件就是外部的查询的where条件。正如我们所料,hive发现这个过程是可以一次性完成的,所以进行了优化,放在了reduce阶段来作了。
第3步 数据倾斜
上一步中,我们计算出了所有的相同ip的人的点对 点关系。但是这个结果集会有不少问题,比如如果某个ip是一个公共出口,那么就会出现同一个ip有上万人都在使用,他们互相join展开以后,结果的数据 量会非常大,时间上很慢不说,最终得到的数据实际上很多我们也用不上(这个是基于业务上得考虑),甚至有可能,在展开的时候会出现各种问题,导致计算时间 过长,算不出来。这种情况,我们在hive里面称之为数据倾斜。
SELECT` `/*+ MAPJOIN(b) */``a.``key``, a.value ``FROM` `a ``join` `b ``on` `a.``key` `= b.``key``;
我们的ip计算使用的是自己join自己,所有也没有大小表之分,同时单表的数据量也大到无法完全放进内存,那么是不是就要进行硬算呢?在实际中,因为ip的分布没有倾斜到太过火的程度,硬算也确实可以,但是这里我们换一种方式来稍稍优化一下。首先我们采用bucket的方式来保存之间的用户->ip的数据。使用ip来作为分桶键。 然后set hive.enforce.bucketing = true;开启bucket计算 insert overwrite table tablebbb 结果将会被保存到128个不同的桶中,默认根据ip的hashcode来取模。这样每个桶内的数据基本大概是原数据量的1/100。当然如果原始数据量太大,还可以分桶更加多一些。 set mapred.reduce.tasks=128.然后在查询中cluster by来强制指定进行分桶。这步完成之后,我们再来进行设置 set hive.optimize.bucketmapjoin.sortedmerge=true;
第4步 用udaf取top N
好了,现在我们已经有所有的 user->user的数据,我们希望要一个user->[users]的一对多的记录,但是这个数据量有点大,实际上每个用户大概关联 1000个已经足够了。首先对数据进行排序,排序的依据就是按照用户的相同的ip的数量。然后去最前面的1000个,不足的按实际数量取。这个地方比较容易想到的就是,先group by fromid,toid,然后count一个总数作为新字段,如下 Udaf顾名思义就是一个Aggregate的udf,和之前的udf的区别就是他一般是用来group by的场合中。
自己定义一个evaluator,并且实现其中的一些方法。
public` `static` `class` `MyUDAFEvaluator ``extends` `GenericUDAFEvaluator {`` ``@Override`` ``public` `ObjectInspector init(Mode m, ObjectInspector[] parameters) ``throws` `HiveException {`` ` ` ``}`` ``@Override`` ``public` `void` `reset(AggregationBuffer agg) ``throws` `HiveException {`` ` ` ``}`` ``@Override`` ``public` `AggregationBuffer getNewAggregationBuffer() ``throws` `HiveException {`` ` ` ``}`` ``// Mapside`` ``@Override`` ``public` `void` `iterate(AggregationBuffer agg, Object[] parameters) ``throws` `HiveException {`` ` ` ``}`` ``// Mapside`` ``@Override`` ``public` `Object terminatePartial(AggregationBuffer agg) ``throws` `HiveException {`` ` ` ``}`` ``@Override`` ``public` `void` `merge(AggregationBuffer agg, Object partial) ``throws` `HiveException {`` ` ` ``}`` ``// Reduceside`` ``@Override`` ``public` `Object terminate(AggregationBuffer agg) ``throws` `HiveException {`` ` ` ``}``}
在init阶段会传一个Mode进来,这个Mode中定义了以下的几个阶段PARTIAL1: 这个是map阶段,这个阶段会调用iterate(),和terminatePartial() COMPLETE: 这是纯map处理,无reduce的情况出现的阶段,它会调用iterate()和terminate() Ok,了解了udaf,那么可以动手了。Sql如下 其中的getTopN首先在map端,将每一个fromid的关联的toid的次数都记录下来,记录条数代表重复的ip数量,然后按照这个次数进行倒序排序,截取前n个。 从这次从mr转换到hive的过程中,对我们目前的mr和hive进行了一些比较
1. 运算资源消耗
2. 开发成本/维护成本
毫无疑问,hive的开发成本是远低于mr的。如果能熟练的运用udf和transform会更加提高hvie开发的效率。另外对于数据的操作也非常的直观,对于全世界程序员都喜闻乐见的sql语法的继承也让它更加的容易上手。 hive独有的分区管理,方便进行数据的管理。 逻辑的修改和生效很方便。
3. 底层相关性
在使用hive以后,读取文件的时候,再也不用关心文件的格式,文件的分隔符,只要指定一次,hive就会保存好。相比mr来说方便了很多。当侧重关心与业务相关的内容的时候,用hive会比较有优势。而在一些性能要求高,算法研究的时候,mr会更加适合。
hive是基于hadoop的数据仓库。
那么为什么说hive是基于Hadoop的呢?
之所以说hive是构建在Hadoop之上的数据仓库,简单的说是因为:
①数据存储在hdfs上
②数据计算用mapreduce
Hive是一种建立在Hadoop文件系统上的数据仓库架构,并对存储在HDFS中的数据进行分析和管理;它可以将结构化的数据文件映射为一张数据库表,并提供完整的 SQL 查询功能,可以将 SQL 语句转换为 MapReduce 任务进行运行,通过自己的 SQL 去查询分析需要的内容,这套 SQL 简称 Hive SQL(HQL),使不熟悉MapReduce 的用户也能很方便地利用 SQL 语言对数据进行查询、汇总、分析。
Hive不支持更改数据的操作,Hive基于数据仓库,提供静态数据的动态查询。其使用类SQL语言,底层经过编译转为MapReduce程序,在hadoop上运行,数据存储在HDFS上。
简述有Hive之后,为何还要学mapreduce
hive本身只是在mr上封装,应用场景自然更局限,不可能满足所有需求
有些场景是不能用hive来实现,就需要mr来实现。
结构复杂的日志文件,首先要经过ETL处理(使用mapreduce),得到的数据再有hive处理比较合适。直接让hive处理结构复杂的数据估计很难处理。
业务比较复杂的,还是必须写mapreduce才能实现。
Hive目前底层还是用MapReduce,以后可能会用Spark,Tez。Hive差不多是一个查询接口,你的SQL语句还是会翻译成MapReduce任务的,你用explain就可以看到这些任务的执行计划。
hive+transform约等于mr。
你觉得Hive是否支持in函数
hive 中用in的时候,
如分时段,分类型,分平台统计点击量
select substr(createtime,12,2) hour,logtype,os_id,count(*) from wizad_mdm_raw_hdfs rawwhere ad_id in ('19829','19830','19831','26657d5ff9020d2abefe558796b99584') and adn=5group by substr(createtime,12,2),logtype,os_id,ad_id
有很多,所以用in。这只有0.3.2后才能使用。
之前版本不支持,这就是网上有人说hive不支持in用法。hive wiki上可以看到
https://en.wikipedia.org/wiki/Apache_Hive
但是in的对象是select子查询的话,是一定不支持的
当输入hive 命令时卡住了,你认为是为什么,从哪些方面考虑
Cpu ,网络,内存
说出Hive 安装数据时,mysql和Derby的区别,为什么安装mysql ,或为什么安装Derby,分别有什么优缺陷
Hive 将元数据存储在 RDBMS 中,一般常用 MySQL 和 Derby。默认情况下,Hive 元数据保存在内嵌的 Derby 数据库中,只能允许一个会话连接,只适合简单的测试。实际生产环境中不适用, 为了支持多用户会话,则需要一个独立的元数据库,使用 MySQL 作为元数据库,Hive 内部对 MySQL 提供了很好的支持。
内置的derby主要问题是并发性能很差,可以理解为单线程操作。
Derby还有一个特性。更换目录执行操作,会找不到相关表等比如在/usr下执行创建表,在/usr下可以找到这个表。在/etc下执行查找这个表,就会找不到
简述Hive 桶表什么,什么作用,举例
Hive 分区是什么,什么作用,该怎么分区
Hive 动态分区和静态分区
Hive 分区重命名
说出Hive 导入数据的过程(表有多个分区,桶)
Hive 排序
什么是Hive join
说说你所理解的Hive 视图操作
Hive 序列函数
简述Hive 自定义函数
知道Hive UDF是什么吗,什么作用,为什么要用
简述Hive 优缺点
一)hive的优点
(1)简单容易上手:提供了类SQL查询语言HQL
(2)可扩展:为超大数据集设计了计算/扩展能力(MR作为计算引擎,HDFS作为存储系统)
一般情况下不需要重启服务Hive可以自由的扩展集群的规模。
(3)提供统一的元数据管理
(4)延展性:Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数
(5)容错:良好的容错性,节点出现问题SQL仍可完成执行
(二)hive的缺点(局限性)
(1)hive的HQL表达能力有限
1)迭代式算法无法表达,比如pagerank
2)数据挖掘方面,比如kmeans
(2)hive的效率比较低
1)hive自动生成的mapreduce作业,通常情况下不够智能化
2)hive调优比较困难,粒度较粗
3)hive可控性差
说说Hive内部表和外部表分别是什么?为什么要建外部表?
Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。 需要注意的是传统数据库对表数据验证是 schema on write(写时模式),而 Hive 在load时是不检查数据是否符合schema的,hive 遵循的是 schema on read(读时模式),只有在读的时候hive才检查、解析具体的数据字段、schema。 读时模式的优势是load data 非常迅速,因为它不需要读取数据进行解析,仅仅进行文件的复制或者移动。 写时模式的优势是提升了查询性能,因为预先解析之后可以对列建立索引,并压缩,但这样也会花费要多的加载时间。
被managed 修饰的是内部表(managed table),被external修饰的为外部表(external table); 区别: 内部表数据由Hive自身管理,外部表数据由HDFS管理; 内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse),外部表数据的存储位置由自己制定; 删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除; 对内部表的修改会将修改直接同步给元数据,而对外部表的表结构和分区进行修改,则需要修复(MSCK REPAIR TABLE table_name;)
Hive 表类型有哪些
Hive表有受控表(内部表)、外部表、分区表、桶表四种。
hive是基于hadoop的数据仓库。
那么为什么说hive是基于Hadoop的呢?
之所以说hive是构建在Hadoop之上的数据仓库,简单的说是因为:
①数据存储在hdfs上
②数据计算用mapreduce
Hive是一种建立在Hadoop文件系统上的数据仓库架构,并对存储在HDFS中的数据进行分析和管理;它可以将结构化的数据文件映射为一张数据库表,并提供完整的 SQL 查询功能,可以将 SQL 语句转换为 MapReduce 任务进行运行,通过自己的 SQL 去查询分析需要的内容,这套 SQL 简称 Hive SQL(HQL),使不熟悉MapReduce 的用户也能很方便地利用 SQL 语言对数据进行查询、汇总、分析。
Hive不支持更改数据的操作,Hive基于数据仓库,提供静态数据的动态查询。其使用类SQL语言,底层经过编译转为MapReduce程序,在hadoop上运行,数据存储在HDFS上。
说出Hive 如何调优,提升效率 ---没看
https://blog.csdn.net/WYpersist/article/details/80030499
https://blog.csdn.net/WYpersist/article/details/80030921
https://blog.csdn.net/WYpersist/article/details/80032327
说出Hive 数据清洗的过程
Hive 编程题
5、海量数据分布在100台电脑上,统计出这批数据的TOP10。(写出核心算法思路)
6、背景:现有商品,买家,卖家三个实体,实现一个小小型的交易系统
1)给出表结构设计
2)帅选出没有买过商品的用户
3)写出sql 语句,帅选出仅仅购买了面粉的用户
HIVE与RDBMS关系数据库的区别
1、hive存储的数据量比较大,适合海量数据,适合存储轨迹类历史数据,适合用来做离线分析、数据挖掘运算,
事务性较差,实时性较差
rdbms一般数据量相对来说不会太大,适合事务性计算,实时性较好,更加接近上层业务
2、hive的计算引擎是hadoop的mapreduce,存储是hadoop的hdfs文件系统,
rdbms的引擎由数据库自己设计实现例如mysql的innoDB,存储用的是数据库服务器本地的文件系统
3、hive由于基于hadoop所以存储和计算的扩展能力都很好,
rdbms在这方面比较弱,比如orcale的分表和扩容就很头疼
4、hive表格没有主键、没有索引、不支持对具体某一行的操作,适合对批量数据的操作,不支持对数据的update操作,
更新的话一般是先删除表然后重新落数据
rdbms事务性强,有主键、索引,支持对具体某一行的增删改查等操作
5、hive的SQL为HQL,与标准的RDBMS的SQL存在有不少的区别,相对来说功能有限
rdbms的SQL为标准SQL,功能较为强大。
Hive分析窗口函数
Hive 数据倾斜类
Hive 取前10条数据
https://blog.csdn.net/wypersist/article/details/80318305
Hive 取最小成绩的记录和最大的记录
Hive 四种排序
https://blog.csdn.net/wypersist/article/details/80314431
Hive 时间函数
Mysql 和hive的区别
Hive 的sql语句和mysql 的sql语句有什么不同
Mysql和derby
Hive存储格式
Hive的存储格式主要有:
1.textfile
Hive的默认存储格式
存储方式:行存储
磁盘开销大数据解析开销大
压缩的text文件 hive无法进行合并和拆分
2.SequenceFile
二进制文件以key,value的形式序列化到文件中
存储方式:行存储
可分割压缩
一般选择block压缩
优势是文件和Hadoop api中的mapfile是相互兼容的
3.rcfile
存储方式:数据按行分块每块按照列存储
压缩快快速列存取
读记录尽量涉及到的block最少
读取需要的列只需要读取每个row group 的头部定义。
读取全量数据的操作性能可能比sequencefile没有明显的优势
4.orc
存储方式:数据按行分块每块按照列存储
压缩快快速列存取
效率比rcfile高,是rcfile的改良版本
5.自定义格式
用户可以通过实现inputformat和 outputformat来自定义输入输出格式
Hive导入数据的几种方式:
1.从本地文件系统中导入
load data local inpath 'customer .data'into table customer;
2.从HDFS上导入
load data inpath '/hive/customer .data'into table customer;
3.从别的表中查询出相应的数据导入
insert into table customer select * fromcustomer_tmp;
我们在做存储评估的时候,因为textfile类型的数据不能直接保存到orc类型的表中,根据上面的几种导入数据的方式我们做一下转换就可以了,先导入到一个textfile类型的表中然后在通过查询导入到另外一个表就可以了
drop table if existsdata.test_pa_merchant_info1;
create external tabledata.test_pa_merchant_info1
(…)
row format delimited fields terminated by'\t' lines terminated by '\n' stored AS orc;
INSERT OVERWRITE TABLEtest_pa_merchant_info1
SELECT * FROM test_pa_merchant_info;
Hive 工作原理
Hive 工作原理流程大致步骤为:
1. 用户提交查询等任务给Driver。
2. 编译器获得该用户的任务Plan。
3. 编译器Compiler根据用户任务去MetaStore中获取需要的Hive的元数据信息。
4. 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后将抽象语法树转换成查询块,将查询块转化为逻辑的查询计划,重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce), 最后选择最佳的策略。
5. 将最终的计划提交给Driver。
6. Driver将计划Plan转交给ExecutionEngine去执行,获取元数据信息,提交给JobTracker或者SourceManager执行该任务,任务会直接读取HDFS中文件进行相应的操作。
7. 获取执行的结果。
8. 取得并返回执行结果。