1、hive建表
2、hive不支持INSERT INTO, UPDATE, DELETE操作
3、静态分区和动态分区的区别
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文件存储格式
压缩比: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,
优化:
(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四种排序
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
建表:
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) 取得并返回执行结果
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的体系结构可以分为以下几个部分:
①用户接口:包括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执行的。