在Windows上对超大(800GB)文本文件的内容进行排序


25

我有一个文本文件,每行有一个单词,文件大小为800GB。我需要按字母顺序对单词进行排序。

我尝试使用Windows 排序程序,方法是:

sort.exe input.txt /o output.txt

出现错误:主内存不足,无法完成排序。

我有32GB的RAM,所以当我尝试使用以下方法指定10GB的内存时:

sort.exe input.txt /o output.txt /M 10000000

我得到:

警告:指定的内存大小已减小为可用的页面内存。

输入记录超过最大长度。指定更大的最大值。

我有什么选择?



10
这不是交叉发布,我不是机器,因此发布并删除其他链接需要几分钟!
玛雅

3
将来让社区转移您的问题
Ramhound

4
在Linux中,您可以应用此方法。对于100Mb的文件,这不是什么大问题。
Eric Duminil

3
您正在使用哪个版本的Windows?使用较旧的Windows Server 2012 R2的sort.exe声称能够使用磁盘上的临时文件进行外部合并排序(而没有记录大小限制)。尝试使用/ T为临时文件指定具有800Gb可用空间的磁盘。而且有关“输入记录超出最大长度”的消息似乎与空格无关-查看/ REC选项并考虑您的行终止符是什么。
davidbak

Answers:


16

我有什么选择?

尝试使用Freeware Command Line Sort Utility CMSort

它使用多个临时文件,然后在最后合并它们。

CMsort正在读取输入文件的记录,直到达到调整的内存为止。然后,对记录进行排序并将其写入临时文件。将重复此操作,直到处理完所有记录。最后,所有临时文件都合并到输出文件中。如果可用内存足够,则无需写入临时文件,也不需要合并。

一位用户报告说,它对130,000,000字节的文件进行了排序。

如果您想自己调整一些代码,还可以对巨大的文本文件进行排序-CodeProject- “对文本文件中的行进行排序的算法,其大小超出了可用内存”


26
哇,130兆字节!!!+1
大卫·佛斯特

3
@DavidPostill您确定Windows的coreutils排序效率不是更高(--parallel如果有多个内核,则可以选择...)?
哈斯图

23

另一种选择是将文件加载到数据库中。EG MySQL和MySQL Workbench。
数据库是处理大文件的理想选择

如果您的输入文件仅包含用换行符分隔的单词,则不难。

安装数据库和MySQL Workbench之后,这就是您需要做的。
首先创建模式(假设单词的长度不能超过255个字符,尽管您可以通过增加参数值来更改它)。第一列“ idwords”是主键。

CREATE SCHEMA `tmp` ;

CREATE TABLE `tmp`.`words` (
  `idwords` INT NOT NULL AUTO_INCREMENT,
  `mywords` VARCHAR(255) NULL,
  PRIMARY KEY (`idwords`));

其次导入数据:EG这会将所有单词导入表中(此步骤可能需要一些时间才能完成。我的建议是先使用一个小的单词文件运行测试,一旦确定格式与较大的一个(截断表。IE将其清除并加载完整的数据集)。

LOAD DATA LOCAL INFILE "C:\\words.txt" INTO TABLE tmp.words
LINES TERMINATED BY '\r\n'
(mywords);


此链接可能有助于获取正确的加载格式。 https://dev.mysql.com/doc/refman/5.7/en/load-data.html
EG如果需要跳过第一行,请执行以下操作。

LOAD DATA LOCAL INFILE "H:\\words.txt" INTO TABLE tmp.words
-- FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(mywords);

最后保存排序的文件。这可能还需要一些时间,具体取决于您的PC。

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
INTO OUTFILE 'C:\\sorted_words.csv';

您也可以根据需要随意搜索数据。EG这将为您提供升序的前50个字(从第0个或第一个字开始)。

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
LIMIT 0, 50 ;

祝你好运
皮特


2
相当大的正确答案。
MonkeyZeus

1
这种方法肯定会更加灵活,例如,如果您发现需要以不同的顺序重新运行排序,则尤其如此。
烧烤

我不在乎您的MySQLMariaDB或任何其他DBMS实例有多快,它不会接近在同一台计算机上运行的SQLite的插入性能。即使有东西一样快,SQLite的这个数据量太大(慢)工艺(相信我,我试过了第一!),所以最好的办法是进行排序,并先删除重复的再插入到数据库,如SQLite的。因此,尽管此解决方案在某些情况下可能是有效的,但对于我尝试做的事情肯定不是。多谢您抽出宝贵时间张贴此讯息。
玛雅

订购mywords将永远进行。即使使用LIMIT,它也将花费整个过程的时间,因为MySQL将必须遍历的每个值mywords并对它们进行排序。要解决此问题,必须在完成后执行以下操作LOAD DATA。向添加索引mywords。现在,您可以按该列进行订购,而无需花费一千年的时间。它更好地加载数据之后,而不是在你创建表的时间(更快的数据负载)来添加索引。
Buttle Butkus

7

sort

有很多算法用于对有序文件和无序文件进行排序[ 1 ]
由于所有这些算法均已实现,因此选择一个已经测试过的程序。

coreutils (来自Linux,但也可用于Windows [ 2 ])中,存在sort能够在多核处理器下并行运行的命令:通常就足够了。

如果您的文件太大,则可以帮助处理拆分(split -l),将文件分成几块,可能使用parallel选项(--parallel),然后使用选项对合并的有序块进行排序-mmerge sort)。此处
介绍了许多方法之一(拆分文件,排序单个块,合并排序的块,删除临时文件)。

笔记:

  • 在Windows 10中,存在所谓的Windows子系统Windows,其中所有Linux示例似乎都更加自然。
  • 使用不同算法进行排序具有不同的执行时间,执行时间根据要排序的数据条目数(O(n m),O(nlogn)...)而变化。
  • 算法的效率取决于原始文件中已经存在的顺序。
    (例如,对于已排序的文件(恰好为N),气泡排序是最快的算法,但在其他情况下效率不高)。

2

为了提供Peter H的替代解决方案,有一个程序q允许对文本文件使用SQL样式的命令。下面的命令将执行相同的操作(从与文件相同目录的命令提示符运行),而无需安装SQL Workbench或创建表。

q "select * from words.txt order by c1"

c1 是第1列的简写。

您可以使用排除重复的单词

q "select distinct c1 from words.txt order by c1"

并将输出发送到另一个文件

q "select distinct c1 from words.txt order by c1" > sorted.txt

知道这是否可以处理800 gig文件吗?
罗林

1
我不确定100%-我使用1200行文件(9KB)测试了上述内容。开发人员页面上有一个“限制”页面,其中没有提及最大文件大小。大文件仍然可能遇到内存问题。
布莱恩(Brian)

3
q无法处理如此大量的数据请记住,如果我无法直接将数据加载到SQLite,那么q在后台使用SQLite是什么使您认为q可以?
玛雅

2

如果每一行中的单词都来自有限的词汇(例如英语),则可以使用TreeMap并记录计数(其中m是唯一值的数量)以O(n + m log m)的时间对列表进行排序。

否则,您可以使用java库big-sorter。它将输入拆分为排序的中间文件,并有效地合并它们(总体O(nlogn))。对文件进行排序如下所示:

Sorter.serializerTextUtf8()
      .input(inputFile)
      .output(outputFile)
      .loggerStdOut() // display some progress
      .sort();

我使用随机生成的16个字符单词创建了一个1.7GB的文件(100m行),并按照上面的142s进行了排序,并基于我使用的方法的O(n log n)计算复杂性,我估计800GB的16个字符单词会在装有SSD的i5 2.3GHz笔记本电脑上,大约需要24小时才能对单线程进行排序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.