3. Hive相关知识点
阅读原文时间:2023年07月10日阅读:1

以下是阅读《Hive编程指南》后整理的一些零散知识点:

1. 有时候用户需要频繁执行一些命令,例如设置系统属性,或增加对于Hadoop的分布式内存,加入自定的Hive扩展的Jave包(JAR文件),我们可以将这些命令加入hiverc文件里,这样每当CLI(command-line interface命令行界面)启动时,在‘hive>’提示符出现前先执行这个hiverc文件。

2. Hive脚本(.hql后缀文件)注释--

3. 在Hive内使用Hadoop的dfs命令,直接在Hive CLI中执行Hadoop的dfs命令就行了,而且更高效,因为Hadoop每次都会启动一个新的JVM实例,而Hive会在同一个进程中执行这些命令。

dfs -ls / ;

4. 1字节=8位(1 byte = 8bit);1字=2字节(1 word = 2 byte);1数字=1字节。

5. Hive的集合数据类型有struct(类似类的对象,字段名.first), map(字典, 字段名['last']), array(数组,数组名[1])。

6. Hive的优点:容错率和纠错率高,能有效避免表命令冲突,能避免误删

  (1) 容错率和纠错率高:传统数据库是写时模式(schema on write),即数据在写入数据库时对模型进行检查。Hive是读时模式(schema on read),即数据检查时发生在查询时。Hive如果在读完去时发现非数值型的字符串的话,对于那些字段会返回null值,尽可能进行纠错。

  (2) 能有效避免表命令冲突:Hive中数据库的概念本质上仅仅是表的一个目录或者命名空间,这样可以避免表命名冲突。

  (3) 能避免误删:Hive不允许用户删除一个包含有表的数据库的,用户要么先删除数据库中的表,然后再删除数据库。要么再删除命令的最后加上关键词CASCADE( drop database if exists table_name cascade; ),这样可以使Hive自行先删除数据中的表。此外, 数据库的元数据不可更改(包括库名和库的目录位置),只能修改数据库的键值对属性值(不是表相关的属性,而是数据库的属性)。

7. 管理表(即内部表)和外部表:Hive创建的表分为管理表(也称内部表),还有外部表。Hive让外部表不具有对数据的所有权,因此删除外部表不会删除这份数据,只是删除了外部表描述表的的元数据信息。使用 describe extended tablename; 。可以查看tableType,若MANGAGED_TABLE,则是管理表,若EXTERNAL_TABLE,则是外部表。

8. 性能调优:聚合性能,JOIN优化(表连接顺序安排),JOIN优化(map-side JOIN),并行执行

  (1)  聚合性能调优: set hive.map.aggr=true; 提高聚合(例如sum,count, avg等)的性能,这个设置会出发map阶段进行顶级聚合过程,非顶级的聚合过程将会在执行一个group by后进行,不过,这个设置将需要更多的内存。

  (2) JOIN优化(表连接顺序安排):Hive假定查询中最后一个表是最大的那个表,在对每行记录进行连接操作时,它会尝试将其它表缓存起来,然后扫描最后那个表进行计算。因此,用户需要保证连接操作中的表的大小从左到右时依次增加的。简单来说,join的顺序应该时从小到大的表连接。使用/*STREAMTABLE*/在表名前可以提供标记机制来显示地告之查询优化器哪张表的大表。

  (3) JOIN优化(map-side JOIN):所有所有表中只有一张表是小表,那么可以在最大的表通过mapper的时候将小表完全放到内存中,Hive可以在map端执行连接过程(称为map-side JOIN),这是因为Hive可以和内存中的小表进行逐一匹配,从而省略掉常规连接操作所需要的reduce过程。即使对于很小的数据集,这个优化也明显地要快于常规的连接操作。其不仅减少了reduce过程,而且有时还可以统计减少map过程的执行步骤。可通过直接开启的配置参数 set hive.auto.convert.join=true; 让JOIN时自动判定大小表去进行优化。另外,Hive默认判定大小的大小阈值时25MB,你也可以进行改动: hive.mapjoin.smalltable.filesize=25000000; 。需要注意的是Hive对于right outer join和full outer join不支持这个优化。

  (4) 并行执行:Hive中某个特定的job可能包含众多阶段且非完全互相依赖的,这样是可以设置 set hive.exec.parallel = true; 开启并行执行job中的阶段,利用好集群。

9. 不能在where语句中使用列别名

10. 尽量避免使用float,因为float和double有时候在对比时会出问题,例如0.2的float值是0.200000100000,而0.2的double值是0.200000000001。可以用cast转化为浮点值例如: cast(0.2 as float) 。对浮点数进行比较时,需要保持极端谨慎的态度,要避免任何从窄类型隐式转换到更广泛类型的操作。

11. Hive的严格模型 set hive.mapred.mode = strict; 可以禁止3种类型的查询:

  (1) 对于分区表,除非where语句中含有分区字段过滤条件来限制数据范围,否则不允许执行,就是不允许扫描所有分区,取数会快些。
  (2) 因为order by为了执行排序会将所有的结果数据分发到同一个reducer中进行处理,严格模式强制要求用户增加这个limit语句可以防止reducer额外执行很长一段时间。
  (3) 限制笛卡尔积的查询,可以高效地将where语句转化成on语句。

12. Hive是按照输入的数据量大小来确定reducer个数,可以通过 dfs -count; 命令来计算输入量大小。

13. Hadoop的job是I/O密集型而不是CPU密集型,压缩可以提高性能,但如果用户job是CPU密集型的话,使用压缩可能会降低执行性能。使用压缩的优势是可以最小化做需要的磁盘储存空间,以及减小磁盘和网络I/O操作。不过文件压缩过程和解压缩过程会增加CPU开销。

14.  虽然压缩文件确实能够节约存储空间,但是在Hadoop中储存裸压缩文件的一个缺点是,通常这些文件是不可分割的,可分隔的文件可以划分成多个部分,由多个mapper并行进行处理。大多数的压缩文件是不可分割的,只能从头读到尾。

15. Hadoop存储格式:

  (1) SequenceFile:其文件是含有键-值对的二进制文件,当Hive将查询转换成MapReduce job时,对于指定的记录,其取决使用哪些合适的键值对。它适用于在Hive和其他Hadoop相关的工具中共享文件,而不适用Hadoop生态系统之外的其它工具。Hadoop的sequence file存储格式可以将一个文件划分成多个块,然后采用一种可分割的方式对块进行压缩。如果想在Hive中使用sequence file存储格式,可以进行下列指定 create table a_sequence_file_table storted as sequencefile; 。sequence file由三种压缩方式:None,record(默认,记录级别),block(块级别,压缩性能最好而且可分割)。

  (2) HAR:Hadoop有一种存储格式名为HAR,就是Hadoop Archive归档文件,一个HAR文件就像在HDFS文件系统中一个TAR文件一样是一个单独的文件,不过其内部可以存放多个文件和文件夹。如果某个特定分区下保存的文件有成千上万且被访问的概率要低很多的话,那么就需要HDFS中的NameNode消耗非常大的代价来管理这些文件,通过将分区下的文件归档成一个巨大的,但同时可以被Hive访问的文件,可以减轻NameNode的压力。不过缺点是HAR文件查询效率不高且不属于压缩,不会节约存储空间。例如:alter table …archive partition语句将表转化成一个归档表,用alter table … unarchive partition可以将HAR中文件提取出来,然后放置到HDFS中。

  (3) RCfile:因为大多数表具有的字段个数都不大,所以大多数Hadoop和Hive存储时行式存储,按块压缩起来处理重复数据比较高效。但有时候查询只需要其中一小部分字段,这时扫描所有行而过滤掉大部分数据显然是个浪费,这时采用RCfile进行列式存储会更利于工作。展示rcfile文件内容可以通过rcfilecat工具实现(bin/hive --service rcfilecat RCFile文件路径)。

16. 加入UDF用户自定义函数的方法:

  (1) 临时加入:将代码打包成JAR文件,使用ADD JAR和CREATE TEMPORARY FUNCTION。
  (2) 永久加入:对于Hive源码得对functionregistry类进行代码修改,然后按照Hive源码分支的编译方式对Hive源码重新编译即可。

17. 函数类方法:UDF、宏命令和Streaming

  (1) UDF:Java编写,UDF是指用户自定义函数。可用于返回array数组和structure结构体,但是它们无法返回多列或多行。UDTF用户自定义表生成函数可以返回多列或多行,其使用的类继承自GenericUDTF接口。

  (2) 宏命令:提供了在HiveQL中调用其它函数的操作符来定义函数的功能,对于特定的情况,使用宏命令比Java编写UDF或使用Hive的streaming功能更加方便,因为宏命令无需额外编写代码或脚本,可以使用 create temporary macro 语法来创建sigmoid函数:

create temporary macro sigmoid (x double) 1.0 / (1.0 + exp(-x));
select sigmoid(2) from src limit 1;

  (3) Streaming:它是Hadoop里的一个API,它的执行效率通常会比UDF或改写InputFormat对象的方式要低,但可以不用写Java代码。Hive提供了多个语法使用streaming,包括map(),reduce()和transform(),通常建议使用常规的transform()语句。streaming可以用unix系统或其衍生系统自带的如cat和sed这样的系统脚本程序处理数据,如下:

select transform (col1, col2)
using '/bin/cat' as (newA int, newB double) from a;

streaming也可以用add file功能将bash shell文件(也能用perl脚本)加入分布式缓存中,新增文件会被存储到每个task节点机器的当前工作目录下,这样就能直接用transform task而不用去找文件在哪了:

add file ${env:HOME}/prog_hive/ctof.sh;
select transform(col1) using 'ctof.sh' as convert from a;

18. SerDe是序列化/反序列化的简写形式。

19. XPATH是XML的路径语言。例如:

hive>select xpath (\'b1b2',\'//@id\')
from src limit 1;

[foo", "bar]

20. 如果想要通过编程的方式远程访问Hive,可以考虑使用HiveServer或者HiveThrift,其允许通过指定端口访问Hive。

21. Hive中的权限管理:

当属性 hive.metastore.authorization.storage.checks 的值为true时,如果用户没有权限删除表底层的文件,Hive就会阻止用户来来删除这样的表。这个参数的默认值时False,而其应该是设置为true的。当在安全模式下执行时,Hive元数据存储要尽可能将hive.metastore.execute.setugi设置为true。

Hive默认情况下,授权模块时不开启的,如果要开启授权,得 set hive.security.authorization.enabled=true; 。

开启授权后便可以对用户(user)、组(group)或者角色(role)授予权限或者回收权限。

  (1)用户授权:例如:

先查看Hive中的用户的系统用户名
hive> set system:user.name;
system:user.name=edward

给该用户授予建表权限

hive>grant create on database default to user edward;

此时该用户便具有的建表权限

hive>create table authorization_test(key int, value string);

通过show grant命令查看授权结果

hive> show grant user edward on database default;

  (2)组授权:当用户很多同时表也很多的情况下,基于用户级别的权限授予会带来高成本的运维成本。更好的选择是基于组(group)级别的权限授予。例如将edward加入某表的选择权限里的组里:

hive>grant select on table authorization_test_group to group edward;

  (3)角色授权:如果用户user和组group仍不够灵活的化,可以用角色role,用户可以放置在角色中同时可以为角色进行授权,角色比较灵活,因为和组不一样,组是由系统外部进行控制的,而角色是由Hive内部进行控制的。如果现在建表可以,但选择表报无权限错误,可以如下角色授权:

# 创建角色存放的地方
hive>create role users_who_can_select_authentication_test_role;

把edward用户放入角色存放点里

hive>grant role users_who_can_select_authentication_test_role to user edward;

把给定的表授权进行选择,授权的目标用户都是给定的角色集里的用户

hive>grant select on table authentication_test_role to role users_who_can_select_authentication_test_role;

# 现在用户就有选择权限了
hive>select * from authentication_test_role;

针对表,我们有授予全部权限授予分区权限两种授予方式:

  (1) 全部权限授予: hive>grant all on table a_part_table to user edward;

  (2) 分区权限授予:只需要将表属性 partition_level_privilege 为true就行了

# 给分区权限前得给alter权限
hive>grant alter on table authorization_part to user edward;

给分区权限

hive>alter table authorization_part set tblproperties("partition_level_privilege"="true");

现在有权限操作表的分区了

hive>alter table authorization_part add partition(ds='3');

撤销用户在表内某分区内容的选择权限

hive>revoke select on table authorization_part partition(ds='3') from user edward;

自动授权:设置 hive.security.authorization.createtable.owner.grants 为创建表的用户自动授予对这张表的指定的权限(对创建表的select和drop权限)。也可以为组或角色设置自动授权,例如 hive.security.authorization.creatable.group.grants 和 hivehive.security.authorization.creatable.role.grants 。

22. Hive中包含了一个使用Apache Zookeeper进行锁定表的功能。锁还是有帮助的,比如有时候,如果一个用户期望锁定一个表,因为有用户会使用insert overwrite这样的语句去修改表,而同时第2各用户也在用这个表做查询,那么这样的查询可能会失败或者产生无效的结果。用户可以显示地管理锁,例如:

hive>lock table people exclusive;

锁后就不能查询了,想要查询可以解锁

hive>unlock table people;

  1. 使用count(1)比count(某字段)来计算行数更快,因为没有列引用意味着没有序列化和反序列化的过程,前者会更快。

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器