在Apache Spark中按密钥对csv文件进行排序

时间:2016-03-19 13:25:24

标签: java sorting csv apache-spark

我有一个csv文件,其中包含以下格式的数据:

id,  name,  surname,   morecolumns
5,   John,  Lok,       more
2,   John2, Lok2,      more
1,   John3, Lok3,      more
etc..

我想使用id作为键对我的csv文件进行排序,并将排序后的结果存储在另一个文件中。

到目前为止我为了创建(id,rest_of_line)的JavaPairs而做了什么。

    SparkConf conf = new SparkConf().setAppName.....;

    JavaSparkContext sc = new JavaSparkContext(conf);

    JavaRDD<String> file = sc.textFile("inputfile.csv");

    // extract the header
    JavaRDD<String> lines = file.filter(s -> !s.equals(header));

    // create JavaPairs
    JavaPairRDD<Integer, String> pairRdd = lines.mapToPair(
      new PairFunction<String, Integer, String>() {
        public Tuple2<Integer, String> call(final String line) {


            String str = line.split(",", 2)[0];
            String str2 = line.split(",", 2)[1];
            int id = Integer.parseInt(str);

            return new Tuple2(id, str2);
        }
    });

    // sort and save the output
    pairRdd.sortByKey(true, 1);
    pairRdd.coalesce(1).saveAsTextFile("sorted.csv");

这适用于我有小文件的情况。但是,当我使用更大的文件时,输出未正确排序。我认为这是因为排序过程发生在不同的节点上,所以所有节点的所有过程的合并都不能给出预期的输出。

所以,问题是如何使用id作为键对我的csv文件进行排序,并将排序后的结果存储在另一个文件中。

2 个答案:

答案 0 :(得分:0)

方法coalesce可能是应该责备的方法,因为它显然没有合同保证订购或产生的RDD(见Which operations preserve RDD order?)。因此,如果您避免使用此类coalesce,则会对所得到的输出文件进行排序。 如果您想要一个唯一的csv文件,您可以从您正在使用的任何文件系统中获取结果,但要处理它们的实际顺序并合并它们。例如,如果您正在使用HDFS(如@PinoSan所述),则可以使用命令hdfs dfs -getmerge <hdfs-output-dir> <local-file.csv>完成此操作。

答案 1 :(得分:0)

正如@mauriciojost指出的那样,你不应该coalesce。 相反,更好的方法是pairRdd.sortByKey(true,pairRdd.getNumPartitions()).saveAsTextFile(path),以便在保存数据的分区上执行最大可能的工作。