Eliminar rápidamente un directorio gigantesco en Linux en la unidad Ext3 / 4

3

He estado trabajando en algunas deduplicaciones de datos que me obligaron a usar el sistema de archivos como una tabla hash. Esto dio lugar a algunos directorios que tomó horas literales a eliminar el uso de casi cualquier método razonable (es decir rm -rf, ls -f1 | xargs rm, find -delete, etc.)

Bajo los sistemas de archivos Ext2 / 3/4, un directorio es un archivo que contiene una tabla hash desde nombres de archivos hasta números de inodo (¡en mi caso, alcanzando alrededor de 60 MB!) Según tengo entendido, correr rm -rfy amigos es lento, porque sigue esta metodología:

Iterar sobre la tabla hash en el archivo de directorio. Por cada par de nombre de archivo-inodo encontrado, atómicamente:

  1. Disminuya el recuento de nombres en el inodo.
  2. Elimine la entrada de la tabla hash.

(La eliminación de los archivos / inodes ocurre cuando su número de nombres alcanza 0 y no hay programas que tengan descriptores de archivo abiertos que apunten a esos inodes).

Disminuir el recuento de nombres de un inodo es rápido.

Eliminar un archivo (especialmente uno pequeño) también es rápido: uno simplemente designa los bloques de unidades que el archivo posee como gratuitos en la tabla de disponibilidad.

La desaceleración, como puedo ver, surge en la eliminación de entradas de la tabla hash. Cada eliminación probablemente tenga la oportunidad de desencadenar un nuevo hash, ya que observé que el tamaño del archivo de directorio disminuye a medida que se eliminan los archivos.

Lo que pido es doble:

  • ¿Es correcto mi razonamiento, ya que es la manipulación de la tabla hash lo que ralentiza el proceso?
  • Si es así, ¿hay alguna herramienta que haga lo siguiente (y que es así, probablemente mucho más rápido)?

    1. Disminuya el recuento de nombres de cada inodo listado en el archivo de directorio.
    2. Elimine todo el contenido del directorio completo a la vez.
Karl Damgaard Asmussen
fuente

Respuestas:

2

El directorio ext3 / 4 no es una tabla hash per-se. En realidad es un árbol hash. Es decir, el nombre de archivo está en hash y el hash se usa como índice para insertar en un árbol b +. La forma más rápida de eliminar todos los archivos será ordenar los archivos por número de inodo, ya que minimizará las búsquedas de disco necesarias para extraer los inodos de la tabla de inodo a la memoria, y las actualizaciones de la tabla de inodo a medida que los archivos se desasignan . Esto también tenderá a eliminar los archivos en el orden en que se crearon, lo que optimizará la forma en que se deben actualizar los diversos mapas de bits de asignación de bloques e inodos. Una cosa más que puede hacer para ayudar es aumentar el tamaño del diario (elimine el diario usando tune2fs y luego vuelva a crearlo con un tamaño de diario más grande).

En última instancia, debe tener en cuenta que un sistema de archivos no está optimizado para ser una base de datos. Si desea hacer dedup, realmente debería considerar usar una base de datos, y no intentar hackearla usando un script de shell y usando un directorio como una base de datos rápida y sucia. Como has descubierto, eso no funciona terriblemente bien ...

Theodore Ts'o
fuente
Theodore Ts'o responde algunas preguntas aleatorias sobre ext3 / 4. Agradable. :) ¡También he visto al físico galardonado con el Premio Nobel respondiendo sobre Física SE y me encanta cuando suceden estas cosas! Tal vez el Papa en el cristianismo SE podría superar esto, pero no he visto que eso suceda (todavía).
Kamil Maciorowski
¡Gracias por aclarar eso! Y sí, una base de datos hubiera sido mucho mejor; pero configurarlo para trabajar llevaría más tiempo que hackearlo. Trabajo en ciencia de datos y me da vergüenza.
Karl Damgaard Asmussen el
2

Eliminar un árbol completo es una operación costosa, pero puede haber formas de acelerarlo.

¿Intentó la solución que figura en esta respuesta y esta respuesta ? rsyncparece ser el más rápido, ya que optimiza las operaciones de borrado en lugar de simplemente repasando la lista de archivos como rm, find, ... hacer.

Además, ¿probaste esta alternativa?

EDITAR:

Tenga en cuenta: no he comparado estos comandos.

Comandos a los que me refiero en caso de que los enlaces se rompan en el futuro:

rsync comando de los dos primeros enlaces:

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

Tercer enlace: "Moverlos al directorio oculto y luego eliminarlo en segundo plano":

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

Como se explicó en esa respuesta, este enfoque supone que (incluso si la eliminación es muy costosa) ya que la eliminación ocurre en segundo plano en otro árbol, el usuario puede no preocuparse por el costo real. En mi opinión, esto es cierto siempre que no intente cerrar su sesión bash / ssh antes de que ocurra la operación de eliminación. Para arreglar esto, agregué una nohupal rmcomando.

miravalls
fuente
@KamilMaciorowski gracias por sus comentarios. He actualizado mi respuesta siguiendo su sugerencia.
miravalls