赞
踩
Hive 是由 Facebook 开源用于解决海量结构化日志的数据统计工具。它是基于 Hadoop 的一个 数据仓库工具,可以将结构化的数据文件映射为一张表,并提供 类 SQL 查询功能。
其本质就是将 HQL 转化成 MapReduce 程序。
Hive是Hadoop生态系统中比不可少的一个工具,它提供了一种SQL(结构化查询语言)方言,可以查询存储在Hadoop分布式文件系统(HDFS)中的数据或其他和Hadoop集成的文件系统。
大多数数据仓库应用程序都是使用关系数据库进行实现的,并使用SQL作为查询语言。
Hive是一个构建在Hadoop之上的数据仓库工具,它提供了类似于SQL的查询语言——HiveQL,这使得那些熟悉关系型数据库和SQL的开发人员能够更容易地迁移到Hadoop生态系统上。Hive降低了将这些应用程序转移到Hadoop系统上的难度。凡是会使用SQL语言的开发人员都可以很轻松的学习并使用Hive。
如果没有Hive,那么这些用户就必须学习新的语言和工具,然后才能应用到生产环境中。另外,相比其他工具,Hive更便于开发人员将基于SQL的应用程序转移到Hadoop中。如果没有Hive,那么开发者将面临一个艰巨的挑战,如何将他们的SQL应用程序移植到Hadoop上。
(1)优点
(2)缺点
因为其计算是通过MapReduce,MapReduce是批处理,高延迟的。 对于小表查询,MapReduce框架在启动任务、分配资源、执行任务以及回收资源等方面都存在一定的开销,这些开销可能比任务执行的时间还要长,这就会导致处理小表的延迟比较高。
首先客户端提交 HQL 以后,hive 通过 解析器 将 SQL 转换成抽象语法树,然后通过 编译器 生成逻辑执行计划,再通过 优化器 进行优化,最后通过 执行器 转换为可以运行的物理计划,比如 MapReduce/spark,然后提交到 yarn 上执行。
默认是保存在 derby 数据库,但是这有一个缺点:derby 数据库不支持并发,也就是说不能同时两个客户端去操作 derby 数据库,因此通常情况下,都会配置 mysql 去存放元数据。
我认为主要有三点的区别:
从建表语句来看,未被 external 修饰的是内部表,被 external 修饰的就是外部表。
二者主要有两点区别
使用场景:
外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
在做统计分析时候用到的中间表,结果表可以使用内部表,因为这些数据不需要共享,使用内部表更为合适。
hive本身是没有索引的,查询数据时需要全表扫描,分区也就是分目录,可以减少全表扫描。
静态分区:
动态分区
hive.exec.dynamic.partition=true
hive.exec.dynamic.partition.mode-nonstrict
分桶表和分区表的作用都是用来减少全表扫描的。因为并非所有的数据都可以进行合理的分区,所以有了新的技术分桶表。分桶表的分桶规则是,根据分桶字段的hash 值,对桶的个数进行取 余运算,然后得到该数据应该放到哪个桶里面去。
(1)创建语句不同,分区表是 partitioned by,分桶表是 clustered by
(2)分区或分桶字段要求不同,分区字段不能是表中存在的字段,分桶字段一定是表中存在的字段。
(3)表现形式不同,分区表是其实就是分了目录存放数据,分桶表是将一个文件拆分为很多文件存放。
(1)Map Join
Map Join的实现方式有两种,分别是Bucket Map Join和Map Join。
(2)Reduce Join是指将两张表的数据都读入HDFS,然后在reduce端进行join操作。
Reduce Join分为Shuffle Join和Merge Join两种实现方式。
Map Join适用于小表驱动大表的情况,Reduce Join适用于大表驱动小表的情况,不同的实现方式在不同的情况下会有不同的优劣点。
当进行大表和小表的聚合操作时,Hive会根据优化器的规则自动选择合适的执行计划。一般来说,如果小表可以放在内存中,那么会先将小表复制到每个Map Task的内存中进行处理,然后再将结果传输回Reduce Task进行汇总,这个过程被称为Map Join。
复制小表到map task的过程,这个过程被称为Replication:
注意:只有当小表可以全部放入内存中时,才会使用 Map Join 来加速处理。如果小表的数据量太大,无法全部放入内存中,那么就必须使用普通的Reduce Join来处理,这种情况下,小表会和大表一样被划分为多个分片,分发到不同的Map任务上进行处理,最后再通过Reduce任务进行合并。
(1)增加集群资源:通过增加Hadoop集群中的节点数或者增加每个节点的资源,例如内存、CPU等,来提高查询的性能和容错能力。
(2)使用Bucket Map Join:Bucket Map Join是一种将 join 操作划分为多个小任务的技术,可以减少每个任务的数据量,从而降低内存的消耗。在使用Bucket Map Join时,需要将表分桶,且分桶的列应该是 join 条件中的列。(要求表在join列上进行了bucket操作,并且bucket数相同,这样在map端会将两张表中的同一个bucket同时读取进内存中,进行join操作)
(3)使用Map Join:Map Join是一种将小表读入内存中的技术,可以减少内存的消耗。在使用Map Join时,需要将小表进行适当的压缩和优化,以提高查询的性能。
(4)使用索引:在Hive 3.0及以上版本中,可以使用ACID表的索引功能来优化查询,从而降低内存的消耗。通过对大表的索引,可以加速查询的速度,同时减少内存的使用。
Order By:全局排序,只有一个 reducer,缺点: 当数据规模大的时候,就会需要很长的计算时间。
Sort By:分区排序,保证每个 reducer 内有序,一般结合 distribute by 来使用。
使用场景:在生产环境中,order by 用的比较少,容易导致 OOM;一般使用 distribute by+sort by
(1)行转列:一行转一列、多行转一列
CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意多个输入字符串。
CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是NULL,返回值也将为NULL。这个函数会跳过分隔符参数后的任何NULL和空字符串。分隔符将被加到被连接的字符串之间。
COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
COLLECT_LIST(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行不去重汇总,产生arr类型字段。
(2)列转行:
EXPLODE(col):将Hive一列中复杂的 array 或者 map 结构拆分成多行。(如果是array,结果只有一列,如果是map,结果只有key,value两列)
(1)承UDF或者UDAF或者UDTF,实现特定的方法;
(2)打成jar包,上传到服务器
(3)执行命令 add jar路径
,目的是将 jar 包添加到 hive 中
(4)注册临时函数:create temporary function 函数名 as "自定义函数全类名"
(5)在select中使用 UDF 函数
(1)使用 DISTINCT关键字
可以在 SELECT 语句中选择不同的值,以去除重复数据。
例如:SELECT DISTINCT column_name FROM table_name;
(2)使用 GROUP BY
可以使用 GROUP BY 子句和聚合函数去掉重复数据。
例如:SELECT column_name, COUNT(*) FROM table_name GROUP BY column_name;
(3)使用窗口函数
可以使用窗口函数来进行去重。
需要注意的是,这种方法可能会影响性能,因为需要进行排序和分组操作,尤其是在处理大数据集时,可能会非常耗时。总的来说,对于数据去重,推荐使用 GROUP BY 的方式,执行效率较高。在需要处理复杂的去重逻辑时,可以考虑使用窗口函数,但需要注意性能问题。
我们写的是HQL,而它的底层引擎是MapReduce,是分布式计算的,所以自然会出现数据倾斜这种分布式计算的典型问题,就会导致运行时间过长。这里其实熟悉MapReduce原理的已经明白了这条sql跑的慢的原因,因为出现了很严重的数据倾斜,很多个mapper,却只有1个reducer,所有的数据在mapper处理过后全部只流向了一个reducer。
为什么只有一个reducer呢?因为使用了distinct和count(full aggreates),这两个函数产生的MapReduce作业只会产生一个reducer,而且哪怕显式指定set mapred.reduce.tasks=100000也是没用的。所以对于这种去重统计,如果在数据量够大,一般是一亿记录数以上(根据实际情况考虑),建议选择使用count加group by去进行统计,执行速度就会快很多。
总结:在数据量很大的情况下,使用count+group by替换count(distinct)能使作业执行效率和速度得到很大的提升,一般来说数据量越大提升效果越明显。
hive 哪里会产生小文件
- 源数据本身有很多小文件
- 动态分区会产生大量小文件
- reduce个数越多,小文件越多
- 按分区插入数据的时候会产生大量的小文件, 文件个数 = maptask个数 * 分区数
(1)建表优化
(2)语法优化
(3)Job优化
hive.fetch.task.conversion=more
(1)UDF:单行进入,单行输出
(2)UDAF:多行进入,单行输出
(3)UDTF:单行输入,多行输出
不是,从 Hive 0.10.0 版本开始,对于简单的不需要聚合的类似 SELECT from LIMIT n
语句,不需要 MapReduce job,直接通过 Fetch task 获取数据。
Hive的文件存储格式有四种:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET,前面两种是行式存储,后面两种是列式存储。如果为textfile的文件格式,直接load,不需要走MapReduce;如果是其他的类型就需要走MapReduce了,因为其他的类型都涉及到了文件的压缩,这需要借助MapReduce的压缩方式来实现。
(1)TEXTFILE:按行存储,不支持块压缩,默认格式,数据不做压缩,磁盘开销大,加载数据的速度最高;
(2)ORCFile:存储方式:数据按行分块,每块按照列存储压缩快,快速列存取效率比rcfile高,是rcfile的改良版本,使用了索引使用ORC文件格式可以提高hive读、写和处理数据的能力PARQUET:按列存储,相对于ORC,Parquet压缩比较低,查询效率较低
SequenceFile:Hadoop API提供的一种二进制文件,以<key,value>的形式序列化到文件中存储方式:行存储
总结压缩比:ORC > Parquet > textFile(textfile没有进行压缩)
查询速度:三者几乎一致
窗口函数:就是给聚合函数开操作的窗口(在明细查询中,展示汇总的结果)
rank、dense_rank、row_number
LAG(col,n,default_val):往前第n行数据。
LEAD(col,n, default_val):往后第n行数据。
FIRST_VALUE (col,true/false):当前窗口下的第一个值,第二个参数为true,跳过空值。
LAST_VALUE (col,true/false):当前窗口下的最后一个值,第二个参数为true,跳过空值。
NTILE(n):把有序窗口的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。
在SQL中,ROW_NUMBER()、RANK()和DENSE_RANK()是用于排序的窗口函数,它们在生成排序结果时有一些区别:
性能上:count(*)=count(1)>count(主键字段)>count(普通字段)
COUNT DISTINCT 和先 GROUP BY 再 COUNT 的操作在Hive中都用于去重计数。
COUNT DISTINCT 通常会将所有数据发送到一个Reduce任务进行去重计数,容易导致单一任务的负载过重,尤其是在数据量大且倾斜严重的情况下。
union all:对两个结果集直接进行并集操作,记录可能有重复,不会进行排序。
union:对两个结果集进行并集操作,会进行去重,记录不会重复,按字段的默认规则排序。因此,从效率上说,union all 要比union更快。
即mapreduce与spark的区别
开启慢查询日志,记录了在 mysql 中响应时间超过阈值的语句,这个时间默认是10s。
如何解决数据倾斜?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。