apache hive中四种排序order by,sort by, distribute by, cluster by

1. order by

Hive中的order by跟传统的sql语言中的order by作用是一样的,会对查询的结果做一次全局排序,所以说,只有hive的sql中制定了order by所有的数据都会到同一个reducer进行处理(不管有多少map,也不管文件有多少的block只会启动一个reducer)。但是对于大量数据这将会消耗很长的时间去执行。

    这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。

set hive.mapred.mode=nonstrict; (default value / 默认值)
set hive.mapred.mode=strict;
hive> select * from test order by id;     
FAILED: Error in semantic analysis: 1:28 In strict mode, if ORDER BY is specified, LIMIT must also be specified. Error encountered near token 'id'

原因: 在order by 状态下所有数据会到一台服务器进行reduce操作也即只有一个reduce,如果在数据量大的情况下会出现无法输出结果的情况,如果进行 limit n ,那只有  n * map number 条记录而已。只有一个reduce也可以处理过来。

2、sort by

Hive中指定了sort by,那么在每个reducer端都会做排序,也就是说保证了局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)。

  • sort by 不受 hive.mapred.mode 是否为strict ,nostrict 的影响
  •  sort by 的数据只能保证在同一reduce中的数据可以按指定字段排序。 
  • 使用sort by 你可以指定执行的reduce 个数 (set mapred.reduce.tasks=<number>) 这样可以输出更多的数据。
  • 对输出的数据再执行归并排序,即可以得到全部结果。

注意:可以用limit子句大大减少数据量。使用limit n后,传输到reduce端(单机)的数据记录数就减少到n* (map个数)。否则由于数据过大可能出不了结果。

3、ditribute by

ditribute by是控制map的输出在reducer是如何划分的。按照指定的字段对数据进行划分到不同的输出reduce。

默认情况下,MapReduce计算框架会依据map输入的键计算相应的哈希值,然后按照得到的哈希值将键-值对均匀分发到多个reducer中去,不过不幸的是,这也是意味着当我们使用sort by 时,不同reducer的输出内容会有明显的重叠,至少对于排序顺序而已只这样,即使每个reducer的输出的数据都有序的。如果我们想让同一年的数据一起处理,那么就可以使用distribute by 来保证具有相同年份的数据分发到同一个reducer中进行处理,然后使用sort by 来安装我们的期望对数据进行排序:

 hive> insert overwrite local directory '/home/hadoop/out' select * from test order by name distribute by length(name);  

 上边例子中的此方法会根据name的长度划分到不同的reduce中,最终输出到不同的文件中。  length 是内建函数,也可以指定其他的函数或这使用自定义函数。

4、cluster by

cluster by的功能就是distribute by和sort by相结合;

注意被cluster by指定的列只能是降序,不能指定asc和desc。

apache hive 大数据的ETL工具/ 数据仓库

Hive是一个基于Hadoop的数据仓库平台。通过hive,我们可以方便地进行ETL的工作。hive定义了一个类似于SQL的查询语言:HQL,能 够将用户编写的QL转化为相应的。

Mapreduce程序基于Hadoop执行。Hive是Facebook 2008年8月刚开源的一个数据仓库框架,其系统目标与 Pig 有相似之处,但它有一些Pig目前还不支持的机制,比如:更丰富的类型系统、更类似SQL的查询语言、Table/Partition元数据的持久化等。并提供一种HQL语言进行查询,具有扩展性好、延展性好、高容错等特点,多应用于离线数仓建设。

Apache hive 原理架构图

1、架构介绍

存储:Hive底层存储依赖于hdfs,因此也支持hdfs所支持的数据存储格式,如text、json、parquet等。当我们将一个文件映射为Hive中一张表时,只需在建表时告诉Hive,数据中的列名、列分隔符、行分隔符等,Hive就可以自动解析数据。

支持多种压缩格式:bzip2、gzip、lzo、snappy等。通常采用parquet+snappy格式存储。支持计算引擎:原生支持引擎为MapReduce。但也支持其他计算引擎,如Spark、Tez。

元数据存储:derby是Hive内置的元数据存储库,但是derby并发性能差且目前不支持多会话。实际生产中,更多的是采用mysql为Hive的元数据存储库。

  • 内嵌模式:元数据保持在内嵌的Derby模式,只允许一个会话连接
  • 本地独立模式:在本地安装Mysql,把元数据放到Mysql内
  • 远程模式:元数据放置在远程的Mysql数据库。

HQL语句执行:解析器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在hdfs中,并在随后转化为MapReduce任务执行。

2、hwi(hive web interface)

hive web接口启动:./hive –service hwi

浏览器访问:http://localhost:9999/hwi/
默认情况下,Hive元数据保存在内嵌的 Derby 数据库中,只能允许一个会话连接,只适合简单的测试。为了支持多用户多会话,则需要一个独立的元数据库,我们使用 MySQL 作为元数据库,Hive 内部对 MySQL 提供了很好的支持。

3、Hive的数据放在哪儿?

数据在HDFS的warehouse目录下,一个表对应一个子目录。本地的/tmp目录存放日志和执行计划

4、hive的表分为两种,内表和外表。

Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。 在删除表的时候,内部表的元数据和数据会被一起删除, 而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。

5、使用Mysql作为Hive metaStore的存储数据库

表名说明关联键
TBLS所有hive表的基本信息(表名,创建时间,所属者等)TBL_ID,SD_ID
TABLE_PARAM表级属性,(如是否外部表,表注释,最后修改时间等)TBL_ID
COLUMNSHive表字段信息(字段注释,字段名,字段类型,字段序号)SD_ID
SDS所有hive表、表分区所对应的hdfs数据目录和数据格式SD_ID,SERDE_ID
SERDE_PARAM序列化反序列化信息,如行分隔符、列分隔符、NULL的表示字符等SERDE_ID
PARTITIONSHive表分区信息(所属表,分区值)PART_ID,SD_ID,TBL_ID
PARTITION_KEYSHive分区表分区键(即分区字段)TBL_ID
PARTITION_KEY_VALSHive表分区名(键值)PART_ID
hive metddata store in mysql

apache hive reflect函数 基因型的UDF函数

在写hsql(hive sql)的时候,我们可以利用hive自身的函数来处理很多的数据,但是有的时候内置函数没法满足我们的需求时就需要用到UDF(User-Defined Function),而有时我们的需求也很简单,在很多的jar包或者java自身的包中已经存在具体的实现逻辑或者方法。那么我们如何来调用这些已经存在且不需要自己写的函数和方法呢?

apache hive

A java class and method often exists to handle the exact function a user would like to use in hive. Rather then having to write a wrapper UDF to call this method, the majority of these methods can be called using reflect udf. Reflect uses java reflection to instantiate and call methods of objects, it can also call static functions. The method must return a primative type or a type that hive knows how to serialize.

Apache hive reflect

大致含义: 通常存在一个 Java 类和方法来处理用户想要在 Hive 中使用的确切功能。不必编写包装 UDF 来调用此方法,大多数方法都可以使用反射 UDF 调用。Reflect 使用 Java 反射来实例化和调用对象的方法;它还可以调用静态函数。该方法必须返回原始类型或 Hive 知道如何序列化的类型。

SELECT reflect("java.lang.String", "valueOf", 1),
       reflect("java.lang.String", "isEmpty"),
       reflect("java.lang.Math", "max", 2, 3),
       reflect("java.lang.Math", "min", 2, 3),
       reflect("java.lang.Math", "round", 2.5),
       reflect("java.lang.Math", "exp", 1.0),
       reflect("java.lang.Math", "floor", 1.9)
FROM src LIMIT 1;

# 输出: 1   true    3   2   3   2.7182818284590455  1.0

再比如我们在解析URL的时候,java的已存在函数是java.net.URLDecoder.decode(),在hive中如何调用?

hive> select reflect('java.net.URLDecoder','decode',cur) from pv where day_id='2016-05-01';

注意: As of Hive 0.9.0, java_method() is a synonym for reflect(). See Misc. Functions in Hive Operators and UDFs.

参考地址: http://sishuok.com/forum/blogPost/list/6226.html