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


Tengo un proyecto que generará una gran cantidad 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 inicio.

¿Cómo me recomienda almacenar estas imágenes de manera eficiente? (Sistema de archivos NTFS actualmente)

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

¿Qué 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?


75
2017-12-17 16:52


origen


¿Están vinculados a usuarios específicos o simplemente genéricos? ¿Están agrupados de alguna manera?
Sólo genérico. Un montón de imágenes generadas por algún equipo técnico. Los estoy nombrando incrementales desde 1 hasta solo para tener una idea de una referencia de tiempo. - s.mihai
¿Cómo van a ser utilizados / accedidos? ¿A través de una aplicación a medida o qué? - dove
¿Este Eres tu? i46.tinypic.com/1z55k7q.jpg
:)) sí ... 1 mil. imágenes porno :)) - s.mihai


Respuestas:


Recomiendo usar 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, puede usar las 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 bien como un sistema de almacenamiento.

No almacene la ruta real a 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 una ruta desde el número de secuencia. p.ej:

 File path = generatePathFromSequenceNumber(sequenceNumber);

Es más fácil de manejar si necesita cambiar la estructura de directorios de alguna manera. Tal vez necesite mover las imágenes a una ubicación diferente, tal vez se quede sin espacio y comience 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 de directorios:

  1. Primero coloque el número de secuencia con ceros iniciales hasta que tenga al menos una cadena de 12 dígitos. Este es el nombre para su archivo. Es posible que desee agregar un sufijo:
    • 12345 -> 000000012345.jpg
  2. Luego divida la cadena en bloques de 2 o 3 caracteres donde cada bloque denota un nivel de directorio. Tener un número fijo de niveles de directorio (por ejemplo 3):
    • 000000012345 -> 000/000/012
  3. Almacena el archivo en el directorio menos generado:
    • Por lo tanto, la ruta completa y el nombre del archivo para el archivo con ID de secuencia 123 es 000/000/012/00000000012345.jpg
    • Para archivo con id de secuencia 12345678901234 el camino seria 123/456/789/12345678901234.jpg

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

  • El algoritmo anterior le da un sistema donde cada directorio de hoja tiene un máximo de 1000 archivos (si tiene menos de un total de 1 000 000 000 000 de archivos)
  • Puede haber límites de cuántos archivos y subdirectorios puede contener un directorio, por ejemplo Sistema de archivos ext3 en Linux tiene un límite de 31998 subdirectorios por directorio.
  • Es posible que las herramientas normales (WinZip, Windows Explorer, línea de comando, shell bash, etc.) no funcionen muy bien si tiene una gran cantidad de archivos por directorio (> 1000)
  • La estructura del directorio en sí tomará algo de espacio en el disco, por lo que no querrá demasiados directorios.
  • Con la estructura anterior, siempre puede encontrar la ruta correcta para el archivo de imagen con solo mirar el nombre del archivo, en caso de que arruine las estructuras de su directorio.
  • Si necesita acceder a archivos de varias máquinas, considere compartir los archivos a través de un sistema de archivos de red.
  • La estructura de directorios anterior no funcionará si elimina muchos archivos. Deja "agujeros" en la estructura del directorio. Pero como no estás eliminando ningún archivo, debería estar bien.

70
2017-12-17 17:32



¡muy interesante! dividiendo el nombre del archivo ... no pensé en eso. Supongo que esta es la forma elegante de hacerlo: -? - s.mihai
Usar un hash (como MD5) como el nombre del archivo, así como la distribución del directorio, funcionaría. La integridad de los archivos no solo sería un beneficio adicional del esquema de nombres (fácil de verificar), sino que también tendrá una distribución razonablemente uniforme en toda la jerarquía de directorios. Entonces, si tienes un archivo llamado "f6a5b1236dbba1647257cc4646308326.jpg" lo almacenarías en "/ f / 6" (o tan profundo como lo necesites). La profundidad de 2 niveles proporciona 256 directorios, o solo menos de 4000 archivos por directorio para los archivos iniciales de 1 m. También sería muy fácil automatizar la redistribución a un esquema más profundo.
+1 Me di cuenta de que esta respuesta era similar a la que acabo de publicar. - 3dinfluence
Definitivamente estoy de acuerdo en usar el sistema de archivos y crear un identificador artificial para "dividir" los nombres de las carpetas. Pero también debe intentar obtener una distribución aleatoria de identificadores, es decir, no utilice un número de secuencia. Eso te permitiría tener un árbol de carpetas más equilibrado. Además, con la distribución aleatoria puede particionar más fácilmente el árbol en varios sistemas de archivos. También usaría una SAN basada en ZFS con dedup activado y un volumen disperso para cada sistema de archivos. Aún podría usar NTFS utilizando iSCSI para acceder a la SAN. - Michael Dillon
Si va de derecha a izquierda en el paso 2, los archivos se distribuyen uniformemente. Además, no tiene que preocuparse de no estar llenando con suficientes ceros, ya que puede tener un número ilimitado de archivos - ropo


Voy a poner mi valor de 2 centavos en 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 (1 meg-> 1 gig), a menudo modificados, varias versiones del archivo, a las que se accede con bastante frecuencia. Los problemas de la base de datos con los que se almacenan archivos de gran tamaño son extremadamente tediosos de tratar, los problemas de escritura y transacción son complicados y tiene problemas de bloqueo que pueden causar un gran avance. naufragios Tengo más práctica en escribir scripts dbcc y restaurar tablas a partir de copias de seguridad de lo que cualquier persona normal debería siempre tener.

La mayoría de los sistemas más nuevos con los que he trabajado han incluido el almacenamiento de archivos en el sistema de archivos y se han basado en bases de datos para nada más que la indexación. Los sistemas de archivos están diseñados para tomar ese tipo de abuso, son mucho más fáciles de expandir y rara vez se pierde todo el sistema de archivos si una entrada se corrompe.


29
2017-12-17 17:12



sí. nota tomada - s.mihai
¿Has mirado el tipo de datos FILESTREAM de SQL 2008? Es un cruce entre la base de datos y el almacenamiento del sistema de archivos. - NotMe
+1 por quedarse con el servidor de archivos en lugar de una base de datos, ya que realiza operaciones de IO rápidas y poco frecuentes.
¿Qué sucede si solo está almacenando unos pocos cientos de documentos o fotografías por base de datos? ¿Hay alguna desventaja en el uso de la base de datos para el almacenamiento? - Beep beep
+1 ... un sistema de archivos es una especie de "base de datos" de todos modos (ntfs seguro), así que ¿por qué hacerlo demasiado complicado? - akira


Creo que la mayoría de los sitios que tienen que lidiar con esto utilizan algún tipo de hash para asegurarse de que los archivos se distribuyen uniformemente en las carpetas.

Así que diga que tiene un hash de un archivo que es algo como esto 515d7eab9c29349e0cde90381ee8f810
Puede tener esto almacenado en la siguiente ubicación y puede usar la cantidad de niveles que necesita para mantener bajo el número de archivos en cada carpeta.
\51\5d\7e\ab\9c\29\349e0cde90381ee8f810.jpg

He visto este enfoque muchas veces. Aún necesita una base de datos para asignar estos hashes de archivos a un nombre legible por el ser humano y cualquier otro metadato que necesite almacenar. Pero este enfoque se puede escalar bastante bien porque puede comenzar a distribuir el espacio de dirección de hash entre varias computadoras y grupos de almacenamiento, etc.


12
2017-12-17 20:17



Git utiliza un enfoque similar: git-scm.com/book/en/v2/Git-Internals-Git-Objects (para respaldar esta respuesta) - aexl


Idealmente, debería realizar algunas pruebas en tiempos de acceso aleatorio para varias estructuras, ya que la configuración de su disco duro específico, el almacenamiento en caché, la memoria disponible, etc. pueden cambiar estos resultados.

Suponiendo que usted tenga control sobre los nombres de archivo, los dividiría en el nivel de 1000 por directorio. Cuantos más niveles de directorio agregue, más inodos quemará, por lo que hay un push-pull aquí.

P.ej.,

/ root / [0-99] / [0-99] / filename

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 usa una gran cantidad de archivos en una carpeta NTFS (300,000 o más), desactive la generación de nombres de archivos cortos para un mejor rendimiento, y especialmente si los primeros seis caracteres de los nombres de archivos largos son similares".

También debe considerar la desactivación de las funciones del sistema de archivos que no necesita (por ejemplo, la última vez que accedió). http://www.pctools.com/guides/registry/detail/50/


11
2017-12-17 17:01



+1 para deshabilitar la generación del nombre de archivo 8.3 y el último tiempo de acceso; esa fue la primera cosa que me vino a la mente cuando leí "gran número de [archivos]" y "NTFS" (Windows). - rob
enlace caído........................ - Pacerier


Hagas lo que hagas, no los guardes todos en un directorio.

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

Asi que:

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

Usted podría introducir su propia profundidad adecuada requerida.

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


7
2017-12-17 16:58



\ a \ b \ c \ d \ e \ f \ que estoy haciendo ahora, estaba pensando que hay una forma inteligente de hacerlo. - s.mihai
Esa es una solución generalmente aceptada de cómo almacenarlos físicamente. Claramente, generar la URL de la imagen es algo que se puede hacer de forma dinámica en función del nombre del archivo de la imagen. Además, para servirlos, incluso podría introducir subdominios img-a, img-b en el servidor de imágenes si lo desea, para acelerar los tiempos de carga.
Y +1 para "no almacenarlos todos en un directorio". Estoy admitiendo un sistema heredado que ha colocado más de 47000 archivos en un servidor en una sola carpeta, y Explorer solo tarda un minuto en abrir la carpeta. - Mark Ransom
Hacer un \ b \ c \ d \ e \ f \ g hace que la estructura del directorio sea muy profunda y cada directorio contiene solo unos pocos archivos. Es mejor usar más de una letra por nivel de directorio, p. Ej. ab \ cd \ ef \ o abc \ def \. Los directorios también ocupan espacio del disco, por lo que no desea muchos de ellos. - Juha Syrjälä
Tuve que admitir una aplicación que tenía 4 + millones de archivos, todo en un directorio; funcionó sorprendentemente bien, pero NUNCA podría hacer que el explorador abra la carpeta, estaría ordenando continuamente las nuevas adiciones. +1 para que NTFS pueda manejarlo sin morir. - SqlACID


Los almacenaría en el sistema de archivos, pero depende de qué tan rápido crecerá el número de archivos. ¿Están estos archivos alojados en la web? ¿Cuántos usuarios accederían a estos archivos? Estas son las preguntas que deben responderse antes de que pueda darte una mejor recomendación. También me gustaría ver Haystack en Facebook, tienen una muy buena solución para almacenar y entregar imágenes.

Además, si elige el sistema de archivos, tendrá que particionar estos archivos con directorios. He estado estudiando este problema y propuse una solución, pero no es perfecta de ninguna manera. Estoy particionando por tabla hash y los usuarios pueden leer más en mi Blog.


5
2017-12-17 16:59



Las imágenes no son para el acceso frecuente. así que no hay problema con esto. su número crecerá bastante rápido. Supongo que habrá 1mil. marca en 1 mes. - s.mihai
Estoy interesado en la vista del programador para que no piense demasiado en esto. - s.mihai
Por lo tanto, si no necesita un acceso rápido, Haystack probablemente no sea para usted. Usar Directorios para Particiones es la solución más simple desde mi punto de vista. - Lukasz


Tenemos un sistema de tienda de fotos con 4 millones de imágenes. Usamos la base de datos solo para metadatos y todas las imágenes se almacenan en el sistema de archivos utilizando un sistema de nombres inverso, donde los nombres de las carpetas se generan a partir del último dígito del archivo, la última 1, y así sucesivamente. p.ej.: 000001234.jpg se almacena en la estructura de directorios como 4 \ 3 \ 2 \ 1 \ 000001234.jpg.

Este esquema funciona muy bien con el índice de identidad en la base de datos, ya que llena uniformemente la estructura de directorios.


5
2017-12-30 22:10





Punto rápido, no necesita almacenar una ruta de archivo en su base de datos. Solo puede almacenar un valor numérico, si sus archivos se nombran de la manera que describe. Luego, al usar uno de los esquemas de almacenamiento bien definidos que ya hemos discutido, puede obtener el índice como un número y encontrar rápidamente el archivo atravesando la estructura del directorio.


4
2017-12-17 17:18



: -? buen punto rapido solo que ahora no tengo un algoritmo para generar el camino. - s.mihai


El nuevo MS SQL 2008 tiene una nueva característica para manejar estos casos, se llama FILESTREAM. Echar un vistazo:

Descripción general de Microsoft TechNet FILESTREAM


4
2017-12-17 17:24