81 votos

Almacenando un millón de imágenes en el sistema de archivos

Tengo un proyecto que generará un gran número de imágenes. Alrededor de 1,000,000 para empezar. No son imágenes grandes, así que las almacenaré todas en una máquina al principio.

¿Cómo recomiendas almacenar estas imágenes eficientemente? (sistema de archivos NTFS actualmente)

Estoy considerando un esquema de nombres... al principio, todas las imágenes tendrán un nombre incremental de 1 en adelante. Espero que esto me ayude a ordenarlas más tarde si es necesario, y colocarlas en diferentes carpetas.

¿Cuál sería un mejor esquema de nombres?

a/b/c/0 ... z/z/z/999

o

a/b/c/000 ... z/z/z/999

¿Alguna idea sobre esto?

1 votos

¿Están atados a usuarios específicos o son solo genéricos? ¿Están agrupados de alguna manera?

0 votos

Solo genérico. un montón de imágenes generadas por algún equipo técnico. las estoy nombrando incrementalmente de 1 en adelante solo para tener una idea de una referencia de tiempo.

0 votos

¿Cómo se van a utilizar/acceder? ¿A través de una aplicación personalizada o qué?

73voto

Marius Puntos 1296

Recomendaría utilizar un sistema de archivos regular en lugar de bases de datos. Usar el sistema de archivos es más fácil que una base de datos, puedes utilizar herramientas normales para acceder a los archivos, los sistemas de archivos están diseñados para este tipo de uso, etc. NTFS debería funcionar perfectamente como sistema de almacenamiento.

No almacenes la ruta real hacia la base de datos. Es mejor almacenar el número de secuencia de la imagen en la base de datos y tener una función que pueda generar la ruta a partir del número de secuencia. Por ejemplo:

 File path = generatePathFromSequenceNumber(sequenceNumber);

Es más fácil de manejar si necesitas cambiar la estructura del directorio de alguna manera. Tal vez necesitas mover las imágenes a una ubicación diferente, tal vez te quedes sin espacio y empieces a almacenar algunas de las imágenes en el disco A y otras en el disco B, etc. Es más fácil cambiar una función que cambiar las rutas en la base de datos.

Yo usaría este tipo de algoritmo para generar la estructura del directorio:

  1. Primero rellena tu número de secuencia con ceros a la izquierda hasta que tengas al menos una cadena de 12 dígitos. Este es el nombre de tu archivo. Puedes querer añadir un sufijo:
    • 12345 -> 000000012345.jpg
  2. Luego divide la cadena en bloques de 2 o 3 caracteres donde cada bloque denota un nivel de directorio. Tenga un número fijo de niveles de directorio (por ejemplo, 3):
    • 000000012345 -> 000/000/012
  3. Almacena el archivo en el directorio generado:
    • Así que la ruta completa y el nombre de archivo para el archivo con id de secuencia 123 es 000/000/012/00000000012345.jpg
    • Para el archivo con id de secuencia 12345678901234, la ruta sería 123/456/789/12345678901234.jpg

Algunas cosas a considerar sobre las estructuras de directorios y almacenamiento de archivos:

  • El algoritmo anterior te proporciona un sistema donde cada directorio hoja tiene un máximo de 1000 archivos (si tienes menos de un total de 1 000 000 000 000 archivos)
  • Puede haber límites en cuántos archivos y subdirectorios puede contener un directorio, por ejemplo, el sistema de archivos ext3 en Linux tiene un límite de 31998 subdirectorios por directorio.
  • Las herramientas normales (WinZip, Explorador de Windows, línea de comandos, bash shell, etc.) pueden no funcionar muy bien si tienes un gran número de archivos por directorio (> 1000)
  • La estructura del directorio en sí misma ocupará algo de espacio en disco, así que no querrás tener demasiados directorios.
  • Con la estructura anterior, siempre podrás encontrar la ruta correcta del archivo de imagen simplemente mirando el nombre del archivo, si llegas a desordenar tus estructuras de directorios.
  • Si necesitas acceder a archivos desde varias máquinas, considera compartir los archivos a través de un sistema de archivos de red.
  • La estructura del directorio anterior no funcionará si borras muchos archivos. Deja "agujeros" en la estructura del directorio. Pero como no estás eliminando archivos, debería estar bien.

1 votos

¡Muy interesante! Dividir el nombre del archivo ... no se me había ocurrido eso. Supongo que esta es la forma elegante de hacerlo :-?

40 votos

Usar un hash (como MD5) como nombre del archivo, así como la distribución de directorios, funcionaría. No solo la integridad de los archivos sería un beneficio secundario del esquema de nombres (fácilmente verificable), sino que también tendrías una distribución razonablemente uniforme en toda la jerarquía de directorios. Entonces, si tienes un archivo llamado "f6a5b1236dbba1647257cc4646308326.jpg" lo guardarías en "/f/6" (o tan profundo como requieras). 2 niveles de profundidad dan 256 directorios, o un poco menos de 4000 archivos por directorio para los 1m archivos iniciales. También sería muy fácil automatizar la redistribución a un esquema más profundo.

0 votos

+1 Acabo de darme cuenta de que esta respuesta era similar a la que acabo de publicar.

32voto

Satanicpuppy Puntos 4902

Voy a dar mi opinión por valor de 2 centavos sobre un consejo negativo: no vayas con una base de datos.

He estado trabajando con bases de datos de almacenamiento de imágenes durante años: archivos grandes (de 1 megabyte a 1 gigabyte), a menudo cambiantes, múltiples versiones del archivo, accedidos con bastante frecuencia. Los problemas de base de datos que surgen al almacenar archivos grandes son extremadamente tediosos de tratar, los problemas de escritura y transacción son complicados y te encuentras con problemas de bloqueo que pueden causar grandes desastres. Tengo más práctica escribiendo scripts de dbcc y restaurando tablas a partir de copias de seguridad de lo que cualquier persona normal debería jamás tener.

La mayoría de los sistemas más nuevos con los que he trabajado han trasladado el almacenamiento de archivos al sistema de archivos y han confiado en las bases de datos solo para la indexación. Los sistemas de archivos están diseñados para soportar ese tipo de abuso, son mucho más fáciles de ampliar y rara vez pierdes todo el sistema de archivos si una entrada se corrompe.

0 votos

¡Sí. ¡Nota tomada!

5 votos

¿Has revisado el tipo de datos FILESTREAM de SQL 2008? Es una mezcla entre almacenamiento de base de datos y sistema de archivos.

0 votos

+1 en quedarse con el servidor de archivos en lugar de una base de datos, ya que estás realizando operaciones de E/S rápidas e infrecuentes.

12voto

Ray Booysen Puntos 10606

Idealmente, deberías realizar algunas pruebas sobre los tiempos de acceso aleatorio para diversas estructuras, ya que tu configuración específica del disco duro, la caché, la memoria disponible, etc. pueden cambiar estos resultados.

Suponiendo que tengas control sobre los nombres de archivo, los dividiría en niveles de 1000 por directorio. Cuantos más niveles de directorio añadas, más inodos consumes, por lo que hay un equilibrio aquí.

P. ej.,

/root/[0-99]/[0-99]/nombre de archivo

Nota, http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx tiene más detalles sobre la configuración de NTFS. En particular, "Si usas un gran número de archivos en una carpeta NTFS (300,000 o más), desactiva la generación de nombres de archivo cortos para obtener un mejor rendimiento, especialmente si los seis primeros caracteres de los nombres de archivo largos son similares".

También deberías considerar desactivar las características del sistema de archivos que no necesitas (p. ej., la hora de último acceso). http://www.pctools.com/guides/registry/detail/50/

3 votos

+1 por deshabilitar la generación de nombres de archivo 8.3 y la última hora de acceso; es lo primero que me vino a la mente cuando leí "gran cantidad de [archivos]" y "NTFS" (Windows).

0 votos

Enlace abajo........................

8voto

Wim Hollebrandse Puntos 171

Haga lo que haga, no las almacene todas en un solo directorio.

Dependiendo de la distribución de los nombres de estas imágenes, podría crear una estructura de directorios donde tenga carpetas de nivel superior de una sola letra, donde tendría otro conjunto de subcarpetas para la segunda letra de las imágenes, etc.

Entonces:

La carpeta img\a\b\c\d\e\f\g\ contendría las imágenes que comienzan con 'abcdefg' y así sucesivamente.

Puede introducir su propia profundidad apropiada requerida.

Lo bueno de esta solución es que la estructura de directorios actúa efectivamente como una tabla hash/diccionario. Dado el nombre de un archivo de imagen, sabrá su directorio y dado un directorio, sabrá un subconjunto de imágenes que van allí.

0 votos

\a\b\c\d\e\f\ Ahora estoy haciendo, estaba pensando que hay una manera sabia de hacer esto.

1 votos

Esta es una solución generalmente aceptada sobre cómo almacenarlas físicamente. Claramente, generar las URL de las imágenes es algo que se puede hacer fácilmente de forma dinámica basándose en el nombre del archivo de la imagen. Además, para ofrecerlas, incluso podrías introducir subdominios img-a, img-b en el servidor de imágenes si quisieras, para acelerar los tiempos de carga.

0 votos

Wim - eso es exactamente lo que estoy haciendo ahora, solo pensé que hay algunas otras personas que han tenido este problema.

5voto

Lukasz Puntos 341

Almacenaría estos en el sistema de archivos, pero depende de qué tan rápido crecerá el número de archivos. ¿Estos archivos están alojados en la web? ¿Cuántos usuarios accederían a estos archivos? Estas son las preguntas que necesitan ser respondidas antes de que pueda darte una mejor recomendación. También echaría un vistazo a Haystack de Facebook, tienen una solución muy buena para almacenar y servir imágenes.

También si eliges sistema de archivos necesitarás particionar estos archivos con directorios. He estado investigando este problema y propuesto una solución pero no es perfecta en absoluto. Estoy particionando por tabla hash y usuarios, puedes leer más en mi blog.

0 votos

Las imágenes no están destinadas para un acceso frecuente, así que no hay problema con esto. Su número crecerá bastante rápido. Supongo que alcanzaremos el millón en un mes.

0 votos

Estoy interesado en la perspectiva del programador para no pensar demasiado en esto.

0 votos

Por lo tanto, si no necesitas acceso rápido, probablemente Haystack no sea para ti. En mi opinión, utilizar directorios para particiones es la solución más sencilla.

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X