概述
Hive
hive的概念
- hive由于解决海量结构化日志的数据统计。
- hive是基于hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类sql查询功能
- 本质:将hql转化成MapReduce程序
- hive处理的数据存储在hdfs上
- hive分析数据底层的默认实现是MapReduce
- 执行程序运行在yarn上
hive的优缺点
- 优点
- 操作接口采用类sql语法,提供快速开发的能力
- 避免写MapReduce,减少开发人员的学习成本
- hive的执行延迟高,常用于数据分析,对实时性要求不高的场合
- hive的优势在于处理大数据,对于小数据没有优势,因为hive的执行延迟比较高
- hive支持用户自定义函数
- 缺点
- hive的HQL表达能力有限
- 迭代式计算无法表达
- 数据挖掘方面不擅长
- hive的效率比较低
- hive的底层是mr
- hive的调优比较困难,粒度较粗
- hive的HQL表达能力有限
Hive架构原理
- 用户接口:client(hive shell、jdbc、webUI)
- 元数据:metastore
- 元数据包含:表名、表所属的数据库、表的 拥有者、列和分区的字段、表的类型、表的数据所在目录等
- hadoop:使用hdfs进行存储,使用mr进行计算
- 驱动器(driver):分析器、编译器、优化器、执行器
- 分析器:将sql字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成的。比如antlr:对AST进行语法分析,判断:表是否存在,字段是否存在、sql语义是否有误
- 编译器:将AST编译成逻辑执行计划
- 优化器:对逻辑执行计划进行优化
- 执行器:把逻辑执行计划转换成可以运行的物理计划。即mr
- hive通过给用户提供的一系列交互式接口,接收用户的sql指令,使用自己的driver,结合元数据,将这些指令转换为MapReduce,提交到yarn执行,最后返回结果输出到用户交互接
hive和数据库的比较
- hive和数据库除了拥有类似的查询语言,再无类似之处
- 数据库可以应用在online的应用中,但是hive是为了数据仓库而设计的
- 查询语言:HQL(类sql)
- 数据存储位置:hdfs上,而数据库存在块设备或者本地文件系统中
- 数据更新:hive由于是为数据仓库设计的,而数据仓库的内容是读多写少的。因此,hive不建议对数据的改写,所有的数据都是在加载的时候确定好的。 而数据库用insert into添加数据,update set修改数据
- 索引:hive在家在数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此没有对数据中的某些key建立索引。由于MapReduce的引入,hive可以并行访问数据,即使没有索引,在大数据量的访问,hive仍然可以体现出优势。 数据库往往会针对列建立索引,因此在少量特定条件的数据访问,数据库可以有很高的效率,较低的延迟。
- 执行:大多数查询的执行都是通过hadoop提供的MapReduce来实现的。 而数据库通常有自己的执行引擎。
- 执行延迟:hive没有索引,需要全表扫描,因此延迟高。另外hive的底层是MapReduce框架,也快不了。但是MapReduce有并发的优势,在大数据的情况下就有优势了
- 可扩展:hive可以无限扩展,但是数据库扩展却非常有限
- 数据规模:hive支持很大的规模 数据库支持的数据规模较小
- hive的元数据信息默认存储在自带的derby数据库中。
常用交互命令
- hive -e “sql语句;”
- hive -f “sql文件”
- shell中 >是表示追加,>>是覆盖
- 在hive里面查看hdfs文件系统:dfs shell命令
- 查看本地文件系统:! shell命令;
- 到根目录下查看./hivehistory文件可以看到所有历史命令
hive数据仓库位置配置
- 默认位置在/usr/hive/warehouse路径下
- 在仓库目录下,没有对默认的数据库创建文件夹。如果某张表属于default库,直接在数据仓库目录下创建一个文件夹
- 可以在hive-default.xml文件修改数据仓库的路径;
- log存放日志可以到hive-log4j.properties文件修改
数据类型
分隔符设置
- row format delimited fields terminated by ‘,’ :列分隔符
- collection items terminated by ‘_’ :map和array和struct的分隔符
- map keys terminated by ‘:’ :map中的key和value的分隔符
- lines terminated by ‘n’ :行分隔符
- map,struct和array里的元素间关系都可以用同一个字符表示
类型转换
- hive的原子数据类型是可以进行隐式转换的。也可以用cast操作进行强制转换
- 隐式转换规则:
- 任何整数类型都可以隐式地转换为一个范围更广的类型,如tinyint可以转换为int,int转换为bigint
- 所有整数类型、float和string类型都可以隐式的转换成double
- tinyint、smallint、int都可以转换成float
- boolean类型不可以转换成任何其他类型
- cast强转
- cast(“1” as int)
- 强转如果失败,返回的是空值null
-
hive创建内部表时,会将数据移动到数据仓库指向的路径;而外部表,仅仅记录数据所在的路径,不对数据的位置做任何改变。
-
删除数据时,内部表的元数据和真实数据会被一起删除;而外部表只会删除元数据,不删除真实数据
-
like允许用户复制现有的表结构,但是不复制数据
-
加载数据:load data [local] inpath ‘dir’ into table tablename
-
内外表转换:alter table tablename set talproperties(‘EXTERNAL’ = ‘TRUE/FALSE’)
-
查看表的类型:desc formatted tablename
分区表(partitioned by)
- 分区表对应一个hdfs文件系统上的独立文件夹,该文件夹是分区的所有的数据文件。
- hive的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集
- 查询用where分区值可以只查固定的分区的数据,而不用查询全部数据。如果不用where,则是全表扫描
- 分区字段随便选
- 加载数据到固定分区:load data local inpath ‘dir’ into table tablename partition(分区字段=分区取值)
数据从hdfs导出到本地文件系统
- hadoop中的get
- hive -e “sql语句” > 本地路径
分桶
- 分区针对的是数据的存储路径;分桶针对的是数据文件
- 分桶需要设置参数:开启支持分桶
- tablesample(bucket x out of y on column)
- y 必须是 table 总 bucket 数的倍数或者因子。hive 根据 y 的大小,决定抽样的比例。例如,table 总共分了 4 份,当 y=2 时,抽取(4/2=)2 个 bucket 的数据,当 y=8 时,抽取4/8=)1/2
个 bucket 的数据 - x:从哪个bucket开始抽取
- y:桶数/y 表示抽取多少个bucket
- x必须小于等于y的值
- y 必须是 table 总 bucket 数的倍数或者因子。hive 根据 y 的大小,决定抽样的比例。例如,table 总共分了 4 份,当 y=2 时,抽取(4/2=)2 个 bucket 的数据,当 y=8 时,抽取4/8=)1/2
常用查询函数
- NVL:给值为null的数据赋值,她的格式是NVL(string1,replace_with)。功能:如果string1为null,则NVL函数返回replace_with的值,否则返回string1的值。
时间类函数
- data_format:格式化时间。格式为:date_format(‘2020-12-20’,‘yyyy-MM-dd’)=>转换为yyyy-MM-dd的格式
- date_add:时间和天数相加。格式为:date_add(“2020-12-20”,天数);结果:返回2020-12-20加上天数的日期
- date_sub:时间和天数相减
- date_diff:两个时间相减。格式为:date_diff(“2020-12-20”,“2020-12-01”);返回两个日期相减得到的天数
- next_day:下周一的日期。格式:next_day(‘2020-12-20’,‘Monday’);第二个参数为返回下周几,不固定是周一的
- last_day:本月最后一天。格式:last_day(‘2020-12-20’)
- case when:case 属性 when 匹配值1 then 返回值1 else 返回值2 end。
行转列
- concat(string1/col1,string2/col2…):返回输入字符串连接后的结果,支持任意个输入
- concat_ws(separator,str1,str2,…):是特殊形式的concat,以separator为连接符,连接字符串
- collect_set(col):该函数只接受基本数据类型,主要作用是将某字段的值进行去重汇总。返回结果是一个数组类型字段
列转行
- explode(col):将hive一列中复杂的array或者map结构拆分为多行。
- LATERAL VIEW:
- 用法:lateral view udtf(expression) tableAlias AS columnAlias
- 解释:用于和split,explode等udtf函数一起使用,能够将一行数据拆分成多行数据,在此基础上可以对拆分的数据进行聚合。
窗口函数
- over():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化
- current row:当前行
- over(partition by name order by orderdate rows between
UNBOUNDED PRECEDING and current row )
- over(partition by name order by orderdate rows between
- n preceding:往前n行数据
- n following:往后n行数据
- unbounded:起点。unbounded preceding表示从前面的起点;unbounded following表示到后面的终点
- lag(col,n):往前第n行数据
- lead(col,n):往后第n行数据
- rank:
- rank()排序相同时会重复,总数不会变(1,1,1,4)
- dense_rank():排序相同时会重复,总数会减少(1,1,1,2)
- row_number():根据顺序计算(1,2,3,4)#无论重复还是不重复
自定义函数
- udf函数:一进一出
- udaf函数:聚集函数,多进一出
- udtf函数:一进多出
- 编程步骤:
- 继承org.apche.hadoop.hive.ql.UDF
- 实现evaluate函数:evaluate函数支持重载
- 在hive的命令行中创建函数
- 添加jar:add jar linux_jar_path
- 创建function:create function db.function_name AS class_name;
- 注意事项:udf必须要有返回类型,可以返回null,但是返回类型不能为void;
自定义udf函数
- 继承UDF类,重写evaluate方法即可完成
自定义udtf函数
- 继承GenericUDTF类
- 重写方法
- initialize方法:
- 定义输出数据的列名和类型;
- process方法:
- 获取原始数据(第一个传入的参数)和获取分隔符(第二个传入的参数)
- 将原始数据以分隔符进行split
- 将数组中的元素都写出:forward(元素)
- close:回收资源,收尾工作
- initialize方法:
文件格式
- TEXTFILE 和 SEQUENCEFILE 的存储格式都是基于行存储的
- ORC 和 PARQUET 是基于列式存储的。
- parquet文件包括文件的数据和元数据,因此parquet是自解析的
hive调优
- fetch抓取
- hive中对某些情况的查询可以不必使用MapReduce计算。例如select * from employees;在这种情况下,hive可以简单的读取表对应的存储目录下的文件,然后输出查询结果到控制台
- 设置fetch抓取参数为more。(现在默认是more了,旧版本的是默认minimal)
- 设置参数位more后,在全局查找,字段查找、limit查找等都不走MapReduce了!
- 本地模式
- 大多数hadoop job是需要hadoop提供的完整的可扩展性来处理大数据集。
- 但是,hive的输入量是非常小的情况下。为查询执行任务消耗的时间可能会比实际job的执行时间要多得多。这种情况下,可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显的被缩短
- 设置参数开启本地模式为true;
- 表的优化
- 小表、大表join
- 将key相对分散,并且数据量小的表放在join左边,能够减少内存溢出错误发生的几率;在进一步,使用map join让小的维度表先进内存,在map端完成reducer。
- 现在的版本,小表join大表和大表join小表都进行了优化,现在没有什么变化了。
- 大表join大表
- 空key过滤
- join超时是因为某些key对应的数据过多,而相同的key对应的数据都会发送到相同的reducer上,从而导致内存不够
- 分析这些异常的key,如果对应的数据是异常数据,我们可以选择过滤掉这些数据
- 空key转换
- 某些key为空对应的数据很多,但是相应的数据都不是异常数据,必须要包含在join的结果中。
- 解决:为空key的字段赋一个随机值,使得数据均匀的分到不同的reducer上。
- 空key过滤
- mapjoin
- 如果不指定mapjoin或者不符合mapjoin的条件,join会reduce阶段完成join。这就会容易产生数据倾斜。可以用mapjoin把小表全部加装到map端进行join,避免reducer处理
- 步骤:
- 共有两个task。
- 第一个task是本地task,在客户端本地执行的task,负责扫描小表的数据,并将其转换为hashtable的数据结构,并写入本地的文件中。之后将文件加载到distributecache中
- 第二个task是一个没有reducetask的MapReduce,启动maptask扫描大表,在map阶段,根据大表的每一条记录去和distributecache中小表对应的hashtable关联,并直接输出结果
- 小表、大表join
- groupby:负载均衡(预聚合)
- map阶段同一个key数据分发到一个reduce,当一个key数据过大时就容易导致数据倾斜了。
- 并不是所有的操作都是需要在reduce端完成的,很多聚合操作可以在map端进行部分聚合,最后在reduce端得出最终结果(预聚合)
- 步骤:
- 产生两个mr job:
- 第一个mr job中,map的输出结果会随机分配到reduce中,每个reduce中做部分聚合操作,并输出结果。结果:相同的groupByKey有可能会被发送到不同的reduce中,从而起到负载均衡的目的;
- 第二个mr job中,根据上一个mr的数据结果,按照groupByKey分布到reduce中,完成最终的聚合操作。结果:保证相同的groupByKey被分布到同一个reduce中。
- 产生两个mr job:
- count distinct使用先groupBy再count的方式替换
- 避免笛卡尔积
- 避免join不加on条件,或者是无效的on条件
- 行列过滤
- 列过滤:尽量避免写select * from employees;你需要什么列你就写出来,不能习惯性的用*
- 行过滤:先进行where过滤出正确的行记录,然后再进行join。
- 动态分区调整
- 设置动态分区,hive会根据分区字段的数据来进行分区。而平时我们用的是静态分区,即需要我们手动指定加载到哪个分区才行。
- 分区
- mr优化
- 合理设置map数
- map数决定因素:目录下的文件总个数,input的文件大小、集群设置的文件块大小
- 过多的map数会造成资源浪费
- 小文件合并
- 使用combineHiveInputFormat,具有对小文件进行合并的功能
- 默认的hiveinputformat没有对小文件合并的功能
- 复杂文件增加map数
- 当input的文件很多,任务逻辑很复杂的情况下,可以考虑增加map数来使每个map处理的数据量减少,从而提供任务的执行效率
- computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
- 合理设置reduce数
- 过多的启动和初始化reduce也会消耗时间和资源
- 过多的reduce会产生过多 文件,如果文件小就变成了小文件问题了。如果这些文件作为下一个任务的输入,就出现小文件问题了
- 考虑原则:
- 处理大数据量利用合适的reduce数
- 使用单个reduce任务处理数据量大小要合适
- 合理设置map数
- 并行执行:
- hive查询转化成一个或多个阶段。例如MapReduce阶段、抽样阶段、合并阶段、limit阶段。默认情况下,hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段并发是完全互相依赖的,也就是说有些阶段是可以并行执行的。
- job中的并行阶段增多,那么集群利用率就会增加(首先得要有过多的空闲资源)
- 严格模式:防止用户执行不好的影响的查询
- 例如:hive分区表不带where分区值、直接order而不用limit、使用笛卡尔积
- jvm重用:小文件或者task特别多的场景。
- jvm的启动过程会有很大的开销。jvm重用即jvm实例在同一个job中重用N次。
- 缺点:开启jvm重用将一直占用使用到的task插槽,以便进行重用,直到任务完成后才释放。那么如果某个不平衡的job中有某几个reducetask执行的时间要比其他reducetask消耗的时间多的多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,知道所有的task都结束了才会释放
- 推测执行
- 为拖后腿的任务分配一个新的任务(相同)#处理的数据和原始人物相同。谁先完成取谁的结果
- 对偏差非常敏感的任务,不建议使用推测执行
- 压缩
- 执行计划explain
最后
以上就是眼睛大乌龟为你收集整理的Hive知识点Hive的全部内容,希望文章能够帮你解决Hive知识点Hive所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复