hive入门到精通

1、hive建表

  • ROW FORMAT用于指定序列化和反序列化用哪个类。若是没有指定ROW FORMAT或者使用了ROW FORMAT DELIMITED,则将使用自带的一个SerDe:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
    即ROW FORMAT SERDE ‘org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe’
  • FIELDS TERMINATED BY char,定义了字段分割符,LINES TERMINATED BY char定义了行分隔符
  • STORED AS SEQUENCEFILE实际上等于:
    STORED AS INPUTFORMAT ‘org.apache.hadoop.mapred.SequenceFileInputFormat’
    OUTPUTFORMAT ‘org.apache.hadoop.mapred.SequenceFileOutputFormat’
  • collection items terminated by ‘|’ --数组分隔符 结构体分隔符
    map keys terminated by ‘:’ --map分隔符

2、hive不支持INSERT INTO, UPDATE, DELETE操作

  • 插入数据可以用
    load data local inpath “/ljy/ljytest.txt” into table test.ljy_test01;
    如果是使用hive -e,则:hive -e “load data local inpath ‘file:///ljy/ljytest.txt’ into table test.ljy_test01”
    into前面加overwrite表示覆盖
  • 想要删除id=2的记录:insert overwrite table A select id,name from A where id !=2

3、静态分区和动态分区的区别

  • 静态分区和动态分区的建表语句是一样的
    create table test_partition (id string comment ‘ID’, name string comment ‘名字’) comment ‘测试分区’ partitioned by (year int comment ‘年’) ROW FORMAT DELIMITED FIELDS
    TERMINATED BY ‘,’ ;
  • 静态分区和动态分区的插入数据的语句是不一样的
    静态分区:
    insert into table test_partition partition(year=2018, day=20190708) values
    (‘001’,‘张三’); //指定分区字段为某个固定值
    动态分区:
    insert into table test_partition partition(year, day) values (‘001’,‘张三’,2016, 20190708); //在插入值的最后几个字段,按顺序指定分区值。一个分区对应一个目录

4、explode能将一行数据扩展成多行
建表:create table test(‘goods_id’ string), 然后插入数据“1,2,3”。
使用查询:select explode(split(goods_id,’,’)) as goods_id_explode from test, 得到下面结果
goods_id_explode
1
2
3
5、如果只用explode的话,那么只能显示explode作用的那一列,要将所有列都显示出来,那么就需要lateral view
lateral view:侧视图,lateral view在把结果组合,产生一个支持别名表的虚拟表
select * from ljy0523 lateral view explode(split(hobby,"-")) mytable as b; mytable是注册的视图
6、hive文件存储格式

  • textfile
    textfile为默认格式
    存储方式:行存储,磁盘开销大,数据解析开销大 ,压缩的text文件hive无法进行合并和拆分
  • sequencefile
    二进制文件,以的形式序列化到文件中
    存储方式:行存储,可分割,压缩,一般选择block压缩 优势是文件和hadoop api中的mapfile是相互兼容的。
  • rcfile
    存储方式:数据按行分块,每块按照列存储 压缩快,快速列存取,读记录尽量涉及到的block最少,读取需要的列只需要读取每个row group 的头部定义。 读取全量数据的操作 性能可能比sequencefile没有明显的优势
  • orc
    存储方式:数据按行分块,每块按照列存储,压缩快,快速列存取,效率比rcfile高,是rcfile的改良版本

压缩比:bzip2 > gzip > lzo > snappy
压缩速度:snappy > lzo> gzip > bzip2
总结:
textfile 存储空间消耗比较大,并且压缩的text无法分割和合并。查询的效率最低, 优点是可以直接存储,加载数据的速度最高
sequencefile 存储空间消耗最大, 压缩的文件可以分割和合, 查询效率高,需要通过text文件转化来加载
rcfile 存储空间最小,查询的效率最高 ,需要通过text文件转化来加载,加载的速度最低
个人建议:text,seqfile能不用就尽量不要用 ,最好是选择orc

7、创建hive表时STORED AS TEXTFILE 等价于 STORED AS INPUTFORMAT ‘org.apache.hadoop.mapred.TextInputFormat’
相比TEXTFILE和SEQUENCEFILE,RCFILE由于列式存储方式,数据加载时性能消耗较大,但是具有较好的压缩比和查询响应。数据仓库的特点是一次写入、多次读取,因此,整体来看,RCFILE相比其余两种格式具有较明显的优势。
8、hive修改表名:ALTER TABLE old_name RENAME TO new_name
修改字段类型:Alter table 表名 change column 原字段名称 现字段名称 数据类型
9、hive load插入方式比insert插入方式效率更高,因为insert插入方式需要去MySQL检查元数据信息
10、hive优化

  • 设置合理的map/reduce的task数,能有效提升性能。
    比如,10w+级别的计算,用160个reduce,那是相当的浪费,1个足够。
    调整Map数量:如果目录下的文件较多,会启动多个Map作业,造成Map作业启动时间远大于处理时间,这样会造成很大的资源浪费,所以需要合并小文件,减少Map数量。
    如果目录下的文件并不大,但是记录条数较多(比如维度表),且处理逻辑复杂,这时候用一个Map执行效率不一定好,通过设置切分文件大小小于默认值,用多个Map去执行,效率可能会更高。
    调整Reduce数量:Reduce数越多最终输出的数据文件也多,同时启动和初始化化会更多资源。

  • 了解数据分布,自己动手解决数据倾斜问题是个不错的选择。set hive.groupby.skewindata=true;这是通用的算法优化,但算法优化有时不能适应特定业务背景,开发人员了解业务,了解数据,可以通过业务逻辑精确有效的解决数据倾斜问题

  • 对小文件进行合并

  • Hive建表时默认的文件存储格式是textfile(行式存储格式),建表时尽可能使用列式文件存储格式 RCFILE\ORC\PARQUET,提升字段查询效率,同时降低存储空间。

  • SET hive.exec.parallel=true (默认false)
    在一个sql里面包含多个子sql,设置这个参数前,先执行sql1再执行sql2, 加了这个参数后,同时执行sql1和sql2

  • 在查询中先做条件过滤,生成数据量小的子表,然后再做关联。

  • 在业务逻辑优化效果的不大情况下,有些时候是可以将倾斜的数据单独拿出来处理。最后union回去。

  • group by, 当按照类型进行group by的时候,reduce任务将同类型的数据拉到同一个节点进行聚合,而当其中某一组的数据量过大时,会出现其他组的计算已经完成而这里还没计算完成,其他节点的一直等待这个节点的任务执行完成,所以会看到一直map 100% reduce 99%的情况。   
    解决方法:
    方案1:set hive.map.aggr=true
    方案2:set hive.groupby.skewindata=true
    hive.map.aggr=true 这个配置项代表是否在map端进行聚合,相当于MR里面的combiner优化。
    hive.groupby.skwindata=true当选项设定为 true,生成的查询计划会有两个MR Job。第一个MR Job中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的; 第二个 MR Job 再根据预处理的数据结果按照GroupBy Key分布到Reduce(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中)

  • hive join优化
    hive join原理:将on后面出现的所有字段作为map的输出key,将所需的字段作为value,同时为每个表打上不同标记tag,即map输出为(key,)。然后通过shuffle,同一个key都拉取到同一个reduce端,进而实现连接操作。这个也称为reduce side join
    优化:
    (1)map side join
    两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task内存中存在一份(如存到hash table中),然后只扫描大表:对于大表中的每一条记录K/V,在hashtable中查找是否有相同的K的记录,如果有,则连接后输出即可
    2)空值产生的数据倾斜 如果on后面的某个字段有大量空值,那么空值就会聚集在一个reduce里面
    解决办法:
    1.空值不参与关联: select * from a join b on a.user_id = b.user_id and a.user_id is not null union all select * from log a where
    a.user_id is null;
    2.给空值赋予新的随机key select * from a join b on case when a.user_id is null then concat(‘hive’,rand()) else a.user_id end = b.user_id;

11、union all要求两个表的字段名,字段个数都一样
12、在团队开发中,在hdfs上存放重要数据时不要使用内部表,都是使用外部表关联数据。在删除时不会删除表,只会删除元数据,所以不必担心数据的
15、自定义udf:下面的UDF函数实现了对一个String类型的字符串取HashMD5

//继承UDF类
	public class HashMd5 extends UDF {
		//重写evaluate方法
		public String evaluate(String cookie) {
			return MD5Hash.getMD5AsHex(Bytes.toBytes(cookie)); 
		}
	}

将上面的HashMd5类打成jar包,udf.jar
使用时候,在Hive命令行执行:
add jar file:///tmp/udf.jar;
CREATE temporary function str_md5 as ‘com.lxw1234.hive.udf.HashMd5’;
select str_md5(‘lxw1234.com’) from dual;

16、hive分桶:获取更高的查询效率
Hive 中 table 可以拆分成 Partition table 和 桶(BUCKET),对于Table或者Partition, Hive可以进一步组织成桶,也就是说桶Bucket是更为细粒度的数据范围划分。Bucket是对指定列进行hash,然后根据hash值除以桶的个数进行求余,决定该条记录存放在哪个桶中。桶操作是通过 Partition 的 CLUSTERED BY 实现的,BUCKET 中的数据可以通过 SORT BY 排序
18、hive四种排序

  • order by会对输入做全局排序,因此只有一个Reducer(多个Reducer无法保证全局有序),然而只有一个Reducer,会导致当输入规模较大时,消耗较长的计算时间。
  • sort by不是全局排序,其在数据进入reducer前完成排序,因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只会保证每个reducer的输出有序,并不保证全局有序
  • distribute by是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。sort by为每个reduce产生一个排序文件。在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。
  • cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是倒叙排序,不能指定排序规则为ASC或者DESC

19、hive建表的时候,如果不设置属性,那么默认字段分隔符是\001, 默认的map的分隔符是\002, 默认的map的K-V的分隔符是\003
20、\N为Hive中默认NULL标识,也就是如果往hive中插入\N,那么hive查询的时候会显示NULL,可以使用serialization.null.format来指定Hive中保存和标识NULL,可以设置为默认的\N
21、源数据是json格式,或者array>格式,则可以这样建hive表:
如数据源:{“student”: {“name”:“king”,“age”:11},“sub_score”:[{“subject”:“语文”,“score”:80},{“subject”:“数学”,“score”:80}]}

建表:
create external table if not exists dw_stg.stu_score(
student map<string,string> comment "学生信息",
sub_score array<map<string,string>> comment '成绩表'
) 
comment "学生成绩表"
# 要用这个序列化方式
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
stored as textfile;

22、开窗函数(其实就是在每一组(每一个分区)里面的数据打上行号),然后取出TopN,其实就是加上一个新字段rank: row_number() OVER (PARTITION BY revenue) rank
DataFrame top3 = hiveContext.sql(“SELECT * FROM (SELECT product,revenue,row_number() OVER (PARTITION BY revenue) rank FROM sales) tmp_sales WHERE rank <=3”)
23、hive union 要去重,效率不高。union all不去重
24、hive执行流程大致步骤为:
(1) 用户提交查询等任务给Driver。
(2) 编译器获得该用户的任务Plan。
(3) 编译器Compiler根据用户任务去MetaStore中获取需要的Hive的元数据信息。
(4) 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后将抽象语法树转换成查询块,将查询块转化为逻辑的查询计划,重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce), 最后选择最佳的策略。
(5) 将最终的计划提交给Driver。
(6) Driver将计划Plan转交给ExecutionEngine去执行,获取元数据信息,提交给JobTracker或SourceManager执行该任务,任务会直接读取HDFS中文件进行相应的操作
(7) 获取执行的结果。
(8) 取得并返回执行结果
hive入门到精通_第1张图片
25、分区和分桶
1)分区:对于分区指定的列,其值相同的分在同一个分区
create table test_partition_table (key string) partitioned by (dt string)
2)分桶:对于分桶指定的列,其值先进行hash,hash值相同的分在同一个分桶
create table test_bucket_table (key string) clustered by (key) into 20 buckets
26、hive架构
hive入门到精通_第2张图片
Hive的体系结构可以分为以下几个部分:
①用户接口:包括CLI(命令行接口,即shell,最常用)、Jdbc(java操作hive,需要hive开启Thrift Server,然后像java连接msyql,然后写sql语句一样操作hive)和WebUi(主要是hue)
其中CLI和WUI是不需要hive开启Thrift Server的
②驱动引擎Driver : 包含编译器 (Compiler) ) ,优化器 (Optimizer) ) ,执行器 (Executor )。Driver 组件完成 HQL 查询语句从词法分析,语法分析,编译,优化,以及生成逻辑执行计划
③Hive元数据库(MetaStore):Hive将表中的元数据信息存储在数据库中,如derby(自带的)、Mysql(实际工作中配置的)。Hive中的解析器在运行的时候会读取元数据库MetaStore中的相关信息。
为什么在实际业务当中不用Hive自带的数据库derby?是因为derby这个数据库具有很大的局限性:derby这个数据库不允许用户打开多个客户端对其进行共享操作,只能有一个客户端打开对其进行操作
④Hadoop:Hive用HDFS进行存储,用MapReduce进行计算-----Hive这个数据仓库的数据存储在HDFS中,业务实际分析计算是利用MapReduce执行的。

你可能感兴趣的:(hive入门到精通)