任何快速排序的巨大的csv文件

时间:2011-07-06 02:32:16

标签: java unix sorting csv

我正在寻找一些java实现的排序算法。该文件可能是巨大的,比如20000 * 600 = 12,000,000行记录。该行以逗号分隔37个字段,我们使用5个字段作为键。是否有可能快速排序,比如30分钟?

如果你有其他方法而不是java,欢迎它可以很容易地集成到java系统中。例如,unix实用程序。

感谢。

编辑:需要排序的行分为600个文件,每个文件20000行,每个文件4mb。最后,我希望他们成为一个大的排序文件。

我正在尝试对unix进行排序,之后会对其进行更新。

编辑:

我将所有文件都附加到一个大文件中,并尝试了unix排序功能,这非常好。排序2gb文件的时间是12-13分钟。对于600个文件,追加操作需要4分钟。

sort -t ',' -k 1,1 -k 4,7 -k 23,23 -k 2,2r big.txt -o sorted.txt

11 个答案:

答案 0 :(得分:2)

调用unix排序程序应为efficient。它会执行多次传递以确保它不是内存耗尽。你可以使用java的Runtime来分叉一个进程,但是进程的输出被重定向,所以你需要一些玩杂耍到get the redirect to work right

public static void sortInUnix(File fileIn, File sortedFile)
        throws IOException, InterruptedException {
    String[] cmd = {
           "cmd", "/c", 
           // above should be changed to "sh", "-c" if on Unix system
           "sort " + fileIn.getAbsolutePath() + " > "
               + sortedFile.getAbsolutePath() };

    Process sortProcess = Runtime.getRuntime().exec(cmd);

    // capture error messages (if any)
    BufferedReader reader = new BufferedReader(new InputStreamReader(
        sortProcess.getErrorStream()));
    String outputS = reader.readLine();
    while (outputS != null) {
        System.err.println(outputS);
        outputS = reader.readLine();
    }

    sortProcess.waitFor();
}

答案 1 :(得分:1)

数据如何以CSV格式显示?它来自关系数据库吗?你可以这样做,无论进程创建什么文件都以正确的顺序写入它的条目,这样你就不必解决这个问题了。

如果你正在做一个简单的词典顺序,你可以尝试使用unix sort,但我不确定它将如何对具有该大小的文件执行。

答案 2 :(得分:0)

Java Lists can be sorted,您可以尝试从那里开始。

答案 3 :(得分:0)

大型服务器上的Python。

import csv
def sort_key( aRow ):
    return aRow['this'], aRow['that'], aRow['the other']
with open('some_file.csv','rb') as source:
   rdr= csv.DictReader( source )
   data = [ row for row in rdr ]
   data.sort( key=sort_key )
   fields= rdr.fieldnames
with open('some_file_sorted.csv', 'wb') as target:
   wtr= csv.DictWriter( target, fields }
   wtr.writerows( data )

这应该相当快。它非常灵活。

在小型机器上,将其分为三遍:装饰,排序,不装饰

装饰:

import csv
def sort_key( aRow ):
    return aRow['this'], aRow['that'], aRow['the other']
with open('some_file.csv','rb') as source:
   rdr= csv.DictReader( source )
   with open('temp.txt','w') as target:
       for row in rdr:
           target.write( "|".join( map(str,sort_key(row)) ) + "|" + row )

第2部分是使用“|”的操作系统排序作为字段分隔符

去除装饰:

with open('sorted_temp.txt','r') as source:
   with open('sorted.csv','w') as target:
       for row in rdr:
           keys, _, data = row.rpartition('|')
           target.write( data )

答案 4 :(得分:0)

好吧,既然你在谈论巨大的数据集,这意味着你无论如何都需要一些外部排序算法。有一些用于java和几乎任何其他语言 - 因为结果必须存储在磁盘上,无论如何你正在使用哪种语言是非常无趣的。

答案 5 :(得分:0)

您没有提及平台,因此很难与指定的时间达成协议。 12x10 ^ 6记录并不多,但排序是一项非常密集的任务。让我们说37个字段,比如说100字节/字段是45GB?这对于大多数机器来说有点多,但如果记录平均为10bytes / field,那么服务器应该能够将整个文件放在RAM中,这是理想的。

我的建议:将文件分成可用RAM的1/2,对每个块进行排序,然后对生成的排序块进行合并排序。这使你可以在内存中进行所有排序,而不是点击交换,这是我怀疑导致任何减速。

Say(1G块,在你可以玩的目录中):

split --line-bytes=1000000000 original_file chunk
for each in chunk* 
do
  sort $each > $each.sorted
done
sort -m chunk*.sorted > original_file.sorted

答案 6 :(得分:0)

正如您所提到的,您的数据集非常庞大。根据您的机器,一次性对它进行排序将非常耗时(如果您尝试使用QuickSort)。 但是因为你希望它能在30分钟内完成。我建议你看看Map Reduce使用 Apache Hadoop作为您的应用程序服务器。

请记住,这不是一种简单的方法,但从长远来看,您可以根据数据大小轻松扩展。 我还指出了Hadoop setup

上的一个很好的链接

通过单节点设置工作并移至Hadoop集群。 如果你被困在任何地方,我会很乐意帮助你。

答案 7 :(得分:0)

你确实需要确保你有适合工作的工具。 (今天,我希望得到一台带有24 GB内存的3.8 GHz电脑供家庭使用。我买了一个新玩具已经有一段时间了。)

但是,如果要对这些行进行排序并且没有足够的硬件,则不需要分解数据,因为它已经在600个文件中。

单独对每个文件进行排序,然后进行600次合并排序(您只需要在内存中保留600行)这不像一次完成所有这些简单,但您可以在手机上进行。 ;)

答案 8 :(得分:0)

由于您有600个较小的文件,因此同时对所有文件进行排序可能会更快。这将耗尽100%的CPU。这就是重点吗?

waitlist= 
for f in ${SOURCE}/*
do 
    sort -t ',' -k 1,1 -k 4,7 -k 23,23 -k 2,2r -o ${f}.srt ${f} &
    waitlist="$waitlist $!"
done
wait $waitlist
LIST=`echo $SOURCE/*.srt`
sort --merge -t ',' -k 1,1 -k 4,7 -k 23,23 -k 2,2r -o sorted.txt ${LIST}

这将同时对600个小文件进行排序,然后合并已排序的文件。它可能比尝试对单个大文件进行排序更快。

答案 9 :(得分:0)

使用Map / Reduce Hadoop进行排序..我推荐Spring Data Hadoop。 Java的。

答案 10 :(得分:0)

使用已发布到Maven Central的Java库big-sorter,它对commons-csv具有可选的依赖性,以进行CSV处理。它通过分割为中间文件,对中间文件进行排序并合并来处理任何大小的文件。

这是一个例子:

鉴于下面的CSV文件,我们将在第二列(“数字”列)上进行排序:

name,number,cost
WIPER BLADE,35,12.55
ALLEN KEY 5MM,27,3.80
Serializer<CSVRecord> serializer = Serializer.csv(
  CSVFormat.DEFAULT
     .withFirstRecordAsHeader()
     .withRecordSeparator("\n"),
  StandardCharsets.UTF_8);
Comparator<CSVRecord> comparator = (x, y) -> {
    int a = Integer.parseInt(x.get("number"));
    int b = Integer.parseInt(y.get("number"));
    return Integer.compare(a, b);
};
Sorter 
  .serializer(serializer) 
  .comparator(comparator) 
  .input(inputFile) 
  .output(outputFile)
  .sort();

结果是:

name,number,cost
ALLEN KEY 5MM,27,3.80
WIPER BLADE,35,12.55

我创建了一个1200万行37列的CSV文件,并在网格中填充了0到100,000之间的随机整数。然后,我使用 big-sorter 在第11列上对2.7GB文件进行了排序,花了 8分钟在具有SSD和最大堆设置为512m的i7上进行单线程处理(-Xmx512m)。

有关更多详细信息,请参见项目README

相关问题