据我所知;
仅按减速器排序
按订单排序全球,但将所有东西推到一个减速器
通过密钥散列智能地将内容分配到reducer中并通过
进行排序所以我的问题是群集是否保证全球秩序?分配通过将相同的密钥放入相同的减速器但是相邻的密钥呢?
我能找到的唯一文件是here,从示例中可以看出它是全局命令的。但从定义来看,我觉得它并不总是这样。
答案 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 x
和SORT 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不会。
这是一个显示重叠范围的更好示例
答案 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个节点群集的示例。
我观察到的,排序依据,排序依据和分配依据的数字是相同,但是内部机制不同。在DISTRIBUTE BY中:相同的列行将转到一个reducer,例如。 DISTRIBUTE BY(City)-在一列中的Bangalore数据,一则化简器中的Delhi数据:
答案 7 :(得分:0)
如果我理解正确
1.sort by - 只对reducer内的数据进行排序
2.order by - 通过将整个数据集推送到单个 reducer 来对事物进行全局排序。如果我们确实有大量数据(倾斜),则此过程将花费大量时间。