最初に明確にclustered by
しておきます。キーを異なるバケットにのみ配布し、clustered by ... sorted by
バケットを並べ替えます。
簡単な実験(以下を参照)を使用すると、デフォルトではグローバルオーダーを取得できないことがわかります。その理由は、デフォルトのパーティショナーが実際のキーの順序に関係なくハッシュコードを使用してキーを分割するためです。
ただし、データを完全に注文することはできます。
動機は、Tom Whiteによる「Hadoop:The Definitive Guide」(第3版、第8章、274ページ、Total Sort)で、TotalOrderPartitionerについて説明しています。
最初にTotalOrderingの質問に答えてから、私が行ったソート関連のHive実験について説明します。
ここで説明しているのは「概念実証」であり、ClauderaのCDH3ディストリビューションを使用して1つの例を処理することができました。
もともと私は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を生成します。私のテストでは、0から10までの4つのバケットとキーを使用しました。アドホックアプローチを使用して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)にコピーしました。
これらの設定を使用して、データをバケット化/並べ替えました(実験リストの最後の項目を参照)。
これが私の実験です。
基本的に、このテーブルには0から9までの値が順序なしで含まれています。
テーブルのコピーがどのように機能するかを示します(使用するreduceタスクの最大数を設定する実際のmapred.reduce.tasksパラメーター)
ハイブ>テーブルtest2(x int);を作成します。
ハイブ>setmapred.reduce.tasks = 4;
ハイブ>挿入上書きテーブルtest2selectax from test a join test b on ax = bx; --自明でないマップを強制するための愚かな参加-reduce
bash> hadoop fs -cat / user / hive / Warehouse / test2 / 000001_0
1
5
9
バケット化を示します。キーが並べ替え順序なしでランダムに割り当てられていることがわかります。
ハイブ>(x)によって4つのバケットにクラスター化されたテーブルtest3(x int)を作成します。
hive> set hive.enforce.bucketing = true;
ハイブ>挿入上書きテーブルtest3select* from test;
bash> hadoop fs -cat / user / hive / Warehouse / test3 / 000000_0
4
8
0
並べ替えによるバケット化。結果は完全にソートされているのではなく、部分的にソートされています
ハイブ>(x)でクラスター化されたテーブルtest4(x int)を(x desc)で4つのバケットにソートして作成します。
ハイブ>挿入上書きテーブルtest4select* from test;
bash> hadoop fs -cat / user / hive / Warehouse / test4 / 000001_0
1
5
9
値が昇順で並べ替えられていることがわかります。CDH3のHiveバグのように見えますか?
ステートメントごとにクラスターなしで部分的にソートされる:
hive> create table test5 as select x from test distribution by x sort by x desc;
bash> hadoop fs -cat / user / hive / Warehouse / test5 / 000001_0
9
5
1
パッチを適用したTotalOrderParitionerを使用します。
hive> set hive.mapred.partitioner = org.apache.hadoop.mapred.lib.TotalOrderPartitioner;
ハイブ>settotal.order.partitioner.natural.order = false
ハイブ>settotal.order.partitioner.path = / user / training / out_data2
ハイブ>(x)でクラスター化されたテーブルtest6(x int)を(x)で4つのバケットにソートして作成します。
ハイブ>挿入上書きテーブルtest6select* 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