Место на диске, необходимое для сортировки unix

В настоящее время я выполняю сортировку UNIX (через GitBash на компьютере с Windows) текстового файла объемом 500 ГБ. Из-за нехватки места на основном диске я использовал параметр -T, чтобы направить временные файлы на диск, где у меня достаточно места для размещения всего файла. Дело в том, что я наблюдал за дисковым пространством и, видимо, временные файлы уже превышают исходный файл. Я не знаю, как далеко это зайдет, но мне интересно, есть ли правило, по которому я могу предсказать, сколько места мне понадобится для временных файлов.


person Stonecraft    schedule 10.08.2016    source источник
comment
Если сортировка Unix работает аналогично сортировке GNU, то начальный проход создает временные файлы на основе размера оперативной памяти. Если предположить, что для сортировки в памяти можно использовать 1 ГБ оперативной памяти, тогда будет создано 500 файлов по 1 ГБ, а затем будет выполнено 16-кратное слияние этих файлов. Также предполагая, что он удаляет файлы после каждого слияния, тогда ему потребуется 516 ГБ пространства, при этом каждый файл будет округлен до границы размера кластера (распределения файлов). При последнем слиянии требуемое дисковое пространство будет в два раза больше размера файла (с округлением до кластерной связи), то есть чуть более 1000 ГБ.   -  person rcgldr    schedule 10.08.2016
comment
Крысы! Похоже, мне придется инвестировать в дополнительное хранилище.   -  person Stonecraft    schedule 10.08.2016
comment
Это последнее слияние также находится во временной папке? Я направил вывод в место, отличное от временного, в надежде избежать двух полных копий файла на одном диске.   -  person Stonecraft    schedule 10.08.2016
comment
Я недооценил пространство для временных файлов. Предположим, что первый проход слияния создает 500 файлов размером 1 ГБ. На следующем этапе 16 файлов размером 1 ГБ объединяются в файлы размером 16 ГБ, занимая 516 ГБ места. На следующем этапе 16 файлов по 16 ГБ объединяются в файлы по 256 ГБ, занимая 756 ГБ места. Последний этап объединяет один файл размером 256 ГБ и один файл размером 244 ГБ для создания выходного файла размером 500 ГБ. Если выходной файл находится на другом диске, то на временном диске требуется около 756 ГБ.   -  person rcgldr    schedule 11.08.2016
comment
Что ж, в итоге произошло то, что 32 временных файла сократились до 16 временных файлов (~ 10 ГБ каждый), а 99 ГБ окончательного файла были записаны на целевой диск, после чего мой компьютер на мгновение завис. Затем я получил sort: write failed: standard output: No space left on device, временная папка была пуста, а на диске, на котором она находилась, было 869 ГБ свободного места, с которого я начал.   -  person Stonecraft    schedule 11.08.2016
comment
Есть ли опция -s (размер памяти)? Если это так, попробуйте -s 1G, чтобы ограничить размер буфера и начального временного файла до 1 ГБ. Насколько большими были эти 32 временных файла?   -  person rcgldr    schedule 11.08.2016
comment
К сожалению, я не подумал смотреть, пока он не упал до 16.   -  person Stonecraft    schedule 11.08.2016
comment
Попробуйте --batch-size=2. Это займет больше времени, но уменьшит место на диске.   -  person rcgldr    schedule 11.08.2016


Ответы (1)


Я бы сделал это вручную, как описано в этом ответе unix.SE. .

Найдите несколько очень простых запросов, которые разделят ваш контент на фрагменты, достаточно маленькие для сортировки. Например, если это файл слов, вы можете создать такие запросы, как grep ^a …, grep ^b … и т. д. Некоторые элементы могут нуждаться в большей детализации, чем другие.

Вы можете написать это так:

#!/bin/bash
for char1 in other {0..9} {a..z}; do
  out="/tmp/sort.$char1.xz"
  echo "Extracting lines starting with '$char1'"
  if [ "$char1" = "other" ]; then char1='[^a-z0-9]'; fi
  grep -i "^$char1" *.txt |xz -c0 > "$out"
  unxz -c "$out" |sort -u >> output.txt || exit 1
  rm "$out"
done
echo "It worked"

Я использую xz -0, потому что он почти такой же быстрый, как gzip -6 по умолчанию в gzip, но гораздо лучше экономит место. Я исключил его из окончательного вывода, чтобы сохранить выходное значение sort -u, но вместо этого вы могли бы использовать проверку размера (iirc, сортировка завершается сбоем с нулевым выводом), а затем использовать sort -u |xz -c0 >> output.txt.xz, поскольку контейнер xz (и gzip) позволяет объединять архивы. (у меня об этом тоже писалось ранее).

Это работает, потому что вывод каждого запуска grep уже отсортирован (0 предшествует 1, который предшествует a и т. д.), поэтому окончательная сборка не должна проходить через sort (обратите внимание, раздел «другое» будет немного отличается, поскольку некоторые небуквенно-цифровые символы находятся перед цифрами, другие - между цифрами и буквами, а третьи - после букв. Вы также можете удалить флаг -i grep и дополнительно перебрать {A..Z}, чтобы учитывать регистр). Каждая отдельная итерация, очевидно, все еще нуждается в сортировке, но, надеюсь, с ними можно справиться.

Если программа завершает работу до завершения всех итераций и говорит «Это сработало», вы можете отредактировать сценарий с более дискретным пакетом для последней итерации, которую она пробовала. Удалите все предыдущие итерации, поскольку они успешно сохранены в файле output.txt.

person Adam Katz    schedule 06.07.2017