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。

发表回复