Java 对一个巨大的csv文件进行任何快速排序

Java 对一个巨大的csv文件进行任何快速排序,java,unix,sorting,csv,Java,Unix,Sorting,Csv,我正在寻找一些排序算法的java实现。文件可能很大,比如20000*600=12000000行记录。该行由37个字段以逗号分隔,我们使用5个字段作为键。能不能快速分类,比如说30分钟 若您有java以外的其他方法,那个么若可以轻松地将其集成到java系统中,那个么它是受欢迎的。例如,unix实用程序 谢谢 编辑:需要排序的行分散到600个文件中,每个文件20000行,每个文件4mb。最后,我希望他们是一个大的排序文件 我正在尝试对unix排序计时,稍后将进行更新 编辑: 我将所有文件添加到一个大

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

若您有java以外的其他方法,那个么若可以轻松地将其集成到java系统中,那个么它是受欢迎的。例如,unix实用程序

谢谢

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

我正在尝试对unix排序计时,稍后将进行更新

编辑:

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

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

,您可以尝试从那里开始。

数据是如何以CSV格式获取的?它是否来自关系数据库?您可以使创建文件的任何进程都以正确的顺序写入其条目,这样您就不必解决这个问题


如果您正在进行简单的词典排序,您可以尝试unix
排序
,但我不确定在大型服务器上的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 )

既然你说的是巨大的数据集,这意味着你无论如何都需要一些外部排序算法。java和几乎任何其他语言都有一些,因为结果必须存储在磁盘上,不管怎样,您使用的语言都是非常乏味的。

您没有提到平台,因此很难在指定的时间内达成一致。12x10^6条记录并不多,但排序是一项相当密集的任务。假设37个字段,假设100字节/字段为45GB?这对于大多数机器来说有点多,但是如果记录平均为10字节/字段,那么您的服务器应该能够在RAM中容纳整个文件,这将是理想的

我的建议是:将文件分为可用RAM的1/2的块,对每个块进行排序,然后合并对排序后的块进行排序。这使您可以在内存中执行所有排序,而不是按swap,我怀疑这会导致任何速度减慢

比如(1G块,在一个你可以玩的目录中):


正如你提到的,你的数据集是巨大的。根据您的机器(如果您尝试快速排序),一次完成所有排序将非常耗时。 但既然你想在30分钟内完成。我建议您使用Map Reduce查看地图 作为应用服务器

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

完成单节点设置并转到Hadoop集群。
如果您在任何地方遇到困难,我都很乐意帮助您。

调用unix排序程序应该很方便。它进行多次传递以确保它不是内存占用器。您可以使用java的运行时来分叉一个进程,但该进程的输出是重定向的,因此您必须进行一些杂耍:


你真的需要确保你有适合这项工作的工具。(今天,我希望能得到一台3.8GHz、24GB内存的家用电脑。我已经有一段时间没有给自己买新玩具了。)

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


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

因为您有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个小文件进行排序,然后合并已排序的文件。它可能比尝试对单个大文件进行排序更快。

使用Map/Reduce Hadoop进行排序。。我推荐SpringDataHadoop。Java。

使用Java库,该库发布到Maven Central,并具有CSV处理的可选依赖项。它通过拆分为中间文件、对中间文件进行排序并合并来处理任意大小的文件

下面是一个例子:

给定下面的CSV文件,我们将在第二列(“数字”列)排序:

Serializer Serializer=Serializer.csv(
CSVFormat.DEFAULT
.withFirstRecordAsHeader()
.withRecordSeparator(“\n”),
标准字符集(UTF_8);
比较器比较器=(x,y)->{
inta=Integer.parseInt(x.get(“number”);
intb=Integer.parseInt(y.get(“number”);
返回整数。比较(a,b);
};
分拣机
.序列化程序(序列化程序)
.比较器(比较器)
.input(输入文件)
.output(输出文件)
.sort();
结果是:

name,number,cost
ALLEN KEY 5MM,27,3.80
WIPER BLADE,35,12.55
我创建了一个包含1200万行37列的CSV文件,并用0到100000之间的随机整数填充网格。然后,我使用big sorter对第11列中的2.7GB文件进行排序,在SSD和最大堆设置为512m的i7上执行单线程操作需要8分钟(
-Xmx512m


有关更多详细信息,请参阅项目。

除了任何内存内排序算法都会完全失败,甚至对于任何中大型数据集都会出现内存不足错误(12E6行,比如说每行500字节,仅数据会产生5.6gb)@Voo:不一定。许多机器上的内存中可能有1200万条记录。12M*.5K是6Gb。@S.洛特:我的思路是,任何将12M记录描述为“巨大”输入的人都会这样做
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}
name,number,cost
WIPER BLADE,35,12.55
ALLEN KEY 5MM,27,3.80
name,number,cost
ALLEN KEY 5MM,27,3.80
WIPER BLADE,35,12.55