3

Я работал над некоторой дедупликацией данных, которая заставила меня использовать файловую систему в качестве хеш-таблицы. Это привело к тому, что некоторые каталоги были удалены буквально часами, используя практически любой разумный метод (например, rm -rf , ls -f1 | xargs rm , find -delete и т.д.)

В файловых системах Ext2/3/4 каталог - это файл, содержащий хэш-таблицу от имен файлов до номеров инодов (в моем случае, около 60 МБ!) Как я понимаю, запуск rm -rf и friends выполняется медленно, потому что он следует этой методологии:

Выполните итерацию по хеш-таблице в файле каталога. Для каждой пары имя файла-inode встречается атомарно:

  1. Уменьшить счетчик имен в индоде.
  2. Удалить запись из хеш-таблицы.

(Удаление файлов / инодов происходит, когда их количество имен достигает 0, и нет программ с открытыми файловыми дескрипторами, которые указывают на эти иноды.)

Уменьшение количества имен в inode происходит быстро.

Удаление файла (особенно небольшого) также выполняется быстро: в таблице доступности можно просто указать, что диск блокирует принадлежащий файл как свободный.

Замедление, как я могу сказать, возникает в результате удаления записей из хеш-таблицы. У каждого удаления, вероятно, есть шанс вызвать повторное хеширование, поскольку я заметил, что размер файла каталога уменьшается по мере удаления файлов.

То, что я спрашиваю, имеет два аспекта:

  • Верны ли мои рассуждения, поскольку это манипулирование хэш-таблицами, которое замедляет процесс?
  • Если это так, есть ли инструмент, который делает следующее (и, таким образом, вероятно, намного быстрее?)

    1. Уменьшите количество имен для каждого индекса, указанного в файле каталога.
    2. Удалить все содержимое всего каталога за один раз.

2 ответа2

2

Каталог ext3/4 сам по себе не является хеш-таблицей. Это на самом деле хэш-дерево. То есть имя файла хэшируется, а хэш используется как индекс для вставки в дерево b+. Самый быстрый способ удалить все файлы - это отсортировать файлы по номеру инода, поскольку это сведет к минимуму поиск дисков, необходимый для извлечения инодов из таблицы инодов в память, и обновления таблицы инодов по мере освобождения файлов. , Это также приведет к удалению файлов в том порядке, в котором они были созданы, что оптимизирует процесс обновления различных битовых карт выделения блоков и узлов. Еще одна вещь, которую вы можете сделать, это поможет увеличить размер журнала (удалите журнал с помощью tune2fs, а затем заново создайте его с большим размером журнала).

В конечном счете, вы должны иметь в виду, что файловая система не оптимизирована для использования в качестве базы данных. Если вы хотите выполнить дедупликацию, вам действительно следует подумать об использовании базы данных, а не пытаться ее обойти, используя сценарий оболочки и используя каталог в качестве быстрой и грязной базы данных. Как вы обнаружили, это не очень хорошо работает ....

2

Удаление всего дерева - дорогостоящая операция, но могут быть способы ускорить его.

Вы пробовали решение, указанное в этом ответе и в этом ответе? rsync кажется самым быстрым, потому что он оптимизирует операции удаления, а не просто просматривает список файлов как rm , find , ... do.

Кроме того, вы пробовали эту альтернативу?

РЕДАКТИРОВАТЬ:

Обратите внимание: я не тестировал эти команды.

Команды, на которые я ссылаюсь в случае разрыва ссылок в будущем:

Команда rsync первых двух ссылок:

mkdir blank
rsync -a --delete blank/ test/

Третья ссылка: «Переместить их в скрытый каталог, а затем удалить его в фоновом режиме»:

mkdir ../.tmp_to_remove
mv -- * ../.tmp_to_remove
nohup rm -rf ../.tmp_to_remove &

Как объясняется в этом ответе, этот подход предполагает, что (даже если удаление очень дорогое), поскольку удаление происходит в фоновом режиме в другом дереве, пользователь может не заботиться о фактической стоимости. На мой взгляд, это так до тех пор, пока вы не попытаетесь закрыть сеанс bash/ssh до того, как произойдет операция удаления. Чтобы это исправить, я добавил nohup в команду rm .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .