Shell UNIX sort命令如何对非常大的文件进行排序?

Shell UNIX sort命令如何对非常大的文件进行排序?,shell,sorting,Shell,Sorting,UNIXsort命令可以对非常大的文件进行如下排序: sort large_file 排序算法是如何实现的 为什么它不会导致内存的过度消耗?说Unix排序使用外部的R路合并排序算法。该链接涉及更多细节,但本质上它将输入分成更小的部分(适合内存),然后在最后将每个部分合并在一起。sort命令将工作数据存储在临时磁盘文件中(通常在/tmp中).我不熟悉这个程序,但我想它是通过外部排序完成的(大部分问题保存在临时文件中,而相对较小的部分问题一次保存在内存中)。有关此主题的深入讨论,请参见Donald

UNIX
sort
命令可以对非常大的文件进行如下排序:

sort large_file
排序算法是如何实现的


为什么它不会导致内存的过度消耗?

说Unix排序使用外部的R路合并排序算法。该链接涉及更多细节,但本质上它将输入分成更小的部分(适合内存),然后在最后将每个部分合并在一起。

sort命令将工作数据存储在临时磁盘文件中(通常在
/tmp
中).

我不熟悉这个程序,但我想它是通过外部排序完成的(大部分问题保存在临时文件中,而相对较小的部分问题一次保存在内存中)。有关此主题的深入讨论,请参见Donald Knuth's。

警告:此脚本每一块启动一个shell,对于非常大的文件,可能会有数百个shell


这是我为此写的一个脚本。在4处理器机器上,它将分拣性能提高了100%

#! /bin/ksh

MAX_LINES_PER_CHUNK=1000000
ORIGINAL_FILE=$1
SORTED_FILE=$2
CHUNK_FILE_PREFIX=$ORIGINAL_FILE.split.
SORTED_CHUNK_FILES=$CHUNK_FILE_PREFIX*.sorted

usage ()
{
     echo Parallel sort
     echo usage: psort file1 file2
     echo Sorts text file file1 and stores the output in file2
     echo Note: file1 will be split in chunks up to $MAX_LINES_PER_CHUNK lines
     echo  and each chunk will be sorted in parallel
}

# test if we have two arguments on the command line
if [ $# != 2 ]
then
    usage
    exit
fi

#Cleanup any lefover files
rm -f $SORTED_CHUNK_FILES > /dev/null
rm -f $CHUNK_FILE_PREFIX* > /dev/null
rm -f $SORTED_FILE

#Splitting $ORIGINAL_FILE into chunks ...
split -l $MAX_LINES_PER_CHUNK $ORIGINAL_FILE $CHUNK_FILE_PREFIX

for file in $CHUNK_FILE_PREFIX*
do
    sort $file > $file.sorted &
done
wait

#Merging chunks to $SORTED_FILE ...
sort -m $SORTED_CHUNK_FILES > $SORTED_FILE

#Cleanup any lefover files
rm -f $SORTED_CHUNK_FILES > /dev/null
rm -f $CHUNK_FILE_PREFIX* > /dev/null
另见:

内存不应该是个问题-排序已经解决了这个问题。如果您想优化多核CPU的使用,我已经在一个小脚本中实现了这一点(与网络上的一些类似,但比大多数脚本更简单/更干净;)

#/bin/bash
#用法:psort文件名
#在本例中,文件largefile被分割为20 MB的块。
#在合并之前,零件在4个同步线程中进行排序。
# 
#psort largefile.txt 20m 4
#
#由h.p。
拆分-b$2$1$1.5部分
后缀=sorttemp.`date+%s`
n读=3美元
i=0
对于'ls*$1.5部分中的fname*`
做
让我++
排序$fname>$fname.$后缀&
mres=$($i%$nthreads))
测试“$mres”-等式0&等待
完成
等待
排序-m*$后缀
rm$1.5每件*
#/bin/bash
用法()
{
回声并行排序
回显用法:psort file1 file2
echo对文本文件file1进行排序,并将输出存储在file2中
}
#测试命令行上是否有两个参数
如果[$#!=2]
然后
使用
出口
fi
pv$1 |并行--管道--文件排序-S512M |并行-Xj1排序-S1024M-m{}''rm{}>$2

仔细查看排序选项以提高性能,并了解它对您的机器和问题的影响。 Ubuntu上的关键参数是

  • 临时文件的位置-T目录\u名称
  • 要使用的内存量-sn%(占所有要使用内存的N%,越多越好,但 避免过度订阅导致交换到磁盘。您可以使用它,如“-S 80%”使用80%的可用RAM,或“-S 2G”使用2 GB RAM。)

提问者问“为什么没有高内存使用率?”答案来自历史,旧的unix机器很小,默认的内存大小设置很小。根据您的工作负载尽可能大地调整该值,以极大地提高排序性能。将工作目录设置为最快设备上的一个位置,该位置有足够的空间容纳至少1.25*被排序文件的大小

如何使用-T选项对大文件进行排序

我必须对一个大文件的第7列进行排序

我使用的是:

grep vdd  "file name" | sort -nk 7 |
我面临以下错误:

******sort: write failed: /tmp/sort1hc37c: No space left on device******
然后我使用-T选项,如下所示:

grep vdda  "file name" | sort -nk 7  -T /dev/null/ |


这很有趣。我真的不知道它是怎么工作的,但我有一个猜测。它可能会将每个密钥的第一个字符放入二叉树中,当发生冲突时,它也会使用密钥的下一个字符,因此它不会保存比需要更多的密钥。然后,它可以用每个键将偏移量保存到文件中,这样它就可以按顺序查找并打印每一行,@ayaz更有趣的是,如果你不是在磁盘上排序文件,而是在管道中排序,因为很明显,你不能简单地对输入数据进行多次传递。为什么每个人都觉得总是在猜测?你可以对输入进行多次传递-你只需要读取所有输入,将其写入磁盘,然后对磁盘文件进行排序。@Neil-从上下文来看,他显然是在对文件内容进行排序,而不是对文件名进行排序(对于一个名称来说,这是毫无意义的)。我只是想在不太改变上下文的情况下改进这个问题,这样它就可以得到答案,而不是因为一个简单的错误而被否决。使用
-T
指定临时脚本,但它不回答这个问题。split-b将按字节分割,因此,在任意位置截断行,您只需使用sort--parallel N,从GNU sort版本8.11GNU coreutils 8.6开始,实际上这对我来说很有用。我有sort 8.4版本。直接在文件上使用sort(1.9亿行)是行不通的。这个程序只用了不到4分钟就完成了。他的脚本很危险。我的Linux机器在启动了数百个排序进程后失去了响应…@WattsInABox它被称为微妙的flex。这太棒了。我不知道有一个并行包!使用上述方法后,排序时间提高了50%以上。谢谢。我试着对由此生成的文件使用comm for diff,它警告我文件未排序。在一个2.5GB的文件上尝试此操作,在一个带有64GB RAM和-S 80%的盒子上尝试此操作,实际上使用的是完整百分比,即使整个文件小于此百分比。为什么呢?即使它没有使用看起来没有意义的就地排序,sort-S也可能在读取文件内容之前为排序进程预先分配内存。请使用除/dev/null之外的另一个示例目录。
grep vdda  "file name" | sort -nk 7  -T /dev/null/ |