Hive cluster by vs order by vs sort by

时间:2012-12-05 01:42:48

标签: hadoop hql hive

据我所知;

  • 仅按减速器排序

  • 排序
  • 按订单排序全球,但将所有东西推到一个减速器

  • 通过密钥散列智能地将内容分配到reducer中并通过

    进行排序

所以我的问题是群集是否保证全球秩序?分配通过将相同的密钥放入相同的减速器但是相邻的密钥呢?

我能找到的唯一文件是here,从示例中可以看出它是全局命令的。但从定义来看,我觉得它并不总是这样。

8 个答案:

答案 0 :(得分:141)

答案较短:是的,CLUSTER BY保证全局排序,前提是您愿意自己加入多个输出文件。

版本较长:

  • ORDER BY x:保证全局排序,但通过仅通过一个reducer推送所有数据来实现此目的。这对于大型数据集来说基本上是不可接受的。您最终将一个已排序的文件作为输出。
  • SORT BY x:在N个减速器中的每一个处订购数据,但每个减速器都可以接收重叠的数据范围。您最终会得到N个或更多具有重叠范围的排序文件。
  • DISTRIBUTE BY x:确保N个减速器中的每一个都获得x的非重叠范围,但不对每个减速器的输出进行排序。您最终会得到N个或更多未分类范围的未分类文件。
  • CLUSTER BY x:确保N个减速器中的每一个都获得非重叠范围,然后按减速器的那些范围进行排序。这为您提供了全局排序,与执行(DISTRIBUTE BY xSORT BY x)相同。您最终得到N个或更多具有不重叠范围的排序文件。

有意义吗?因此CLUSTER BY基本上是ORDER BY的可扩展版本。

答案 1 :(得分:13)

首先让我澄清一下:clustered by只会将您的密钥分配到不同的存储桶中,clustered by ... sorted by将存储桶排序。

通过简单的实验(见下文),您可以看到默认情况下您不会获得全局订单。原因是默认分区程序使用哈希码分割键,而不管实际的键排序。

但是,您可以完全订购数据。

动机是汤姆怀特的“Hadoop:The Definitive Guide”(第3版,第8章,第274页,总排序),他讨论了TotalOrderPartitioner。

我将首先回答您的TotalOrdering问题,然后描述我所做的几个与排序相关的Hive实验。

请记住:我在这里描述的是“概念证明”,我能够使用Claudera的CDH3发行版处理一个例子。

最初我希望org.apache.hadoop.mapred.lib.TotalOrderPartitioner可以解决问题。不幸的是它没有,因为它看起来像Hive分区的价值,而不是关键。所以我修补它(应该有子类,但我没有时间):

替换

public int getPartition(K key, V value, int numPartitions) {
    return partitions.findPartition(key);
}

public int getPartition(K key, V value, int numPartitions) {
    return partitions.findPartition(value);
}

现在您可以将(修补)TotalOrderPartitioner设置为您的Hive分区程序:

hive> set hive.mapred.partitioner=org.apache.hadoop.mapred.lib.TotalOrderPartitioner;

hive> set total.order.partitioner.natural.order=false

hive> set total.order.partitioner.path=/user/yevgen/out_data2

我也用过

hive> set hive.enforce.bucketing = true; 

hive> set mapred.reduce.tasks=4;

在我的测试中。

文件out_data2告诉TotalOrderPartitioner如何存储值。 您可以通过对数据进行采样来生成out_data2。在我的测试中,我使用了4个桶和0到10的密钥。我使用ad-hoc方法生成了out_data2:

import org.apache.hadoop.util.ToolRunner;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.hive.ql.io.HiveKey;
import org.apache.hadoop.fs.FileSystem;


public class TotalPartitioner extends Configured implements Tool{
    public static void main(String[] args) throws Exception{
            ToolRunner.run(new TotalPartitioner(), args);
    }

    @Override
    public int run(String[] args) throws Exception {
        Path partFile = new Path("/home/yevgen/out_data2");
        FileSystem fs = FileSystem.getLocal(getConf());

        HiveKey key = new HiveKey();
        NullWritable value = NullWritable.get();

        SequenceFile.Writer writer = SequenceFile.createWriter(fs, getConf(), partFile, HiveKey.class, NullWritable.class);
        key.set( new byte[]{1,3}, 0, 2);//partition at 3; 1 came from Hive -- do not know why
        writer.append(key, value);
        key.set( new byte[]{1, 6}, 0, 2);//partition at 6
        writer.append(key, value);
        key.set( new byte[]{1, 9}, 0, 2);//partition at 9
        writer.append(key, value);
        writer.close();
        return 0;
    }

}

然后我将结果out_data2复制到HDFS(到/ user / yevgen / out_data2)

通过这些设置,我得到了数据分段/排序(请参阅我的实验列表中的最后一项)。

这是我的实验。

  • 创建样本数据

    的bash> echo -e“1 \ n3 \ n2 \ n4 \ n5 \ n7 \ n6 \ n8 \ n9 \ n0”> data.txt中

  • 创建基本测试表:

    蜂房> create table test(x int); 蜂房>将数据本地inpath'data.txt'加载到表测试中;

基本上,此表包含0到9之间没有顺序的值。

  • 演示表复制的工作原理(实际上是mapred.reduce.tasks参数,用于设置要使用的最大数量的reduce任务)

    蜂房> create table test2(x int);

    蜂房> set mapred.reduce.tasks = 4;

    蜂房>插入覆盖表test2 从test a中选择a.x. 加入测试b 在a.x = b.x; - 愚蠢的联合迫使非平凡的map-reduce

    的bash> hadoop fs -cat / user / hive / warehouse / test2 / 000001_0

    1

    5

    9

  • 展示分组。您可以看到密钥是随机分配的,没有任何排序顺序:

    蜂房> create table test3(x int) 由(x)聚集成4个桶;

    蜂房> set hive.enforce.bucketing = true;

    蜂房> insert overwrite table test3 select * from test;

    的bash> hadoop fs -cat / user / hive / warehouse / test3 / 000000_0

    4

    8

    0

  • 分拣打包。结果部分排序,未完全排序

    蜂房> create table test4(x int) 聚集(x)排序方式(x desc) 进入4个桶;

    蜂房>插入覆盖表test4 select * from test;

    的bash> hadoop fs -cat / user / hive / warehouse / test4 / 000001_0

    1

    5

    9

您可以看到值按升序排序。看起来像CDH3中的Hive bug?

  • 在没有cluster by语句的情况下进行部分排序:

    蜂房>创建表test5为 选择x 从测试 按x分发 按x desc排序;

    的bash> hadoop fs -cat / user / hive / warehouse / test5 / 000001_0

    9

    5

    1

  • 使用我修补过的TotalOrderParitioner:

    蜂房> set hive.mapred.partitioner = org.apache.hadoop.mapred.lib.TotalOrderPartitioner;

    蜂房> set total.order.partitioner.natural.order = false

    蜂房> set total.order.partitioner.path = / user / training / out_data2

    蜂房> create table test6(x int) 聚集(x)按(x)排序成4个桶;

    蜂房>插入覆盖表test6 select * from test;

    的bash> hadoop fs -cat / user / hive / warehouse / test6 / 000000_0

    1

    2

    0

    的bash> hadoop fs -cat / user / hive / warehouse / test6 / 000001_0

    3

    4

    5

    的bash> hadoop fs -cat / user / hive / warehouse / test6 / 000002_0

    7

    6

    8

    的bash> hadoop fs -cat / user / hive / warehouse / test6 / 000003_0

    9

答案 2 :(得分:6)

CLUSTER BY不会产生全局排序。

接受的答案(Lars Yencken)误导说减速器将接收非重叠范围。正如Anton Zaviriukhin正确指出了BucketedTables文档,CLUSTER BY基本上是DISTRIBUTE BY(与bucketing相同)加上每个bucket / reducer中的SORT BY。并且通过简单地将散列和模型分配到桶中,并且散列函数may保留顺序(如果i> j,则散列i的哈希值),散列值的mod不会。

这是一个显示重叠范围的更好示例

http://myitlearnings.com/bucketing-in-hive/

答案 3 :(得分:4)

据我了解,简答回答是否定的。 你会得到重叠的范围。

来自SortBy documentation: “Cluster By是Distribute By和Sort By的捷径。” “具有相同Distribute By列的所有行将转到相同的reducer。” 但是没有信息可以保证不重叠的范围。

此外,来自DDL BucketedTables documentation: “Hive如何在存储桶中分配行?通常,存储桶编号由表达式hash_function(bucketing_column)mod num_buckets确定。” 我认为Cluster by in Select语句使用相同的原理在reducers之间分配行,因为它的主要用途是用数据填充分块表。

我创建了一个包含1个整数列“a”的表,并在那里插入了0到9的数字。

然后我将减速器的数量设置为2 set mapred.reduce.tasks = 2;

此表中的select数据带有Cluster by子句 select * from my_tab cluster by a;

收到我预期的结果:

0
2
4
6
8
1
3
5
7
9

因此,第一个reducer(数字0)得到偶数(因为它们的模式2给出0)

和第二个减速器(数字1)得到奇数(因为它们的模式2给出1)

这就是“Distribute By”的工作方式。

然后“Sort By”对每个reducer中的结果进行排序。

答案 4 :(得分:0)

Cluster by是每个reducer排序不是全局的。在许多书中也提到了错误或混淆。它特别适用于您将每个部门分配到特定的reducer,然后按每个部门的员工姓名排序,并且不关心部门的顺序,不使用集群,并且随着工作负载在Reducer之间分配,它会更加强大

答案 5 :(得分:0)

排序依据:N个或更多具有重叠范围的排序文件。

OrderBy:单项输出,即已完全订购。

分发者:通过保护N个缩减器中的每一个,获得列的不重叠范围,但不对每个缩减器的输出进行排序。

有关更多信息,http://commandstech.com/hive-sortby-vs-orderby-vs-distributeby-vs-clusterby/

ClusterBy:与上述示例相同,如果我们使用Cluster By x,则两个化简器将进一步对x上的行进行排序:

答案 6 :(得分:0)

用例:如果有一个大型数据集,则应按sort by进行排序,所有集合的reducers在汇总在一起之前在内部对数据进行排序,从而提高了性能。在按顺序排序时,较大的数据集的性能会降低,因为所有数据都通过单个化简器传递,这会增加负载,因此需要更长的时间来执行查询。 请参见以下有关11个节点群集的示例。 enter image description here

这是示例输出示例enter image description here

这是示例排序输出enter image description here

这是示例群集enter image description here

我观察到的,排序依据,排序依据和分配依据的数字是相同,但是内部机制不同。在DISTRIBUTE BY中:相同的列行将转到一个reducer,例如。 DISTRIBUTE BY(City)-在一列中的Bangalore数据,一则化简器中的Delhi数据:

enter image description here

答案 7 :(得分:0)

如果我理解正确

1.sort by - 只对reducer内的数据进行排序

2.order by - 通过将整个数据集推送到单个 reducer 来对事物进行全局排序。如果我们确实有大量数据(倾斜),则此过程将花费大量时间。

  1. cluster by - 通过键哈希智能地将内容分配到 reducer 并进行排序,但不授予全局排序。一个 key(k1) 可以放入两个 reducer。第一个 reducer 获得 10K K1 数据,第二个可能获得 1K k1 数据。