Tengo un proyecto que generará una gran cantidad de imágenes. Alrededor de 1,000,000 para comenzar. No son imágenes grandes, así que las guardaré todas en una máquina al inicio.
¿Cómo recomienda almacenar estas imágenes de manera eficiente? (Sistema de archivos NTFS actualmente)
Estoy considerando un esquema de nomenclatura ... para comenzar, 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 arrojarlas 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?
Respuestas:
Recomiendo usar un sistema de archivos normal en lugar de bases de datos. Usar el sistema de archivos es más fácil que una base de datos, puede usar 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 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 la ruta desde el número de secuencia. p.ej:
Es más fácil de manejar si necesita cambiar la estructura del directorio 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 algunas en el disco B, etc. Es más fácil cambiar una función que cambiar las rutas en la base de datos .
Usaría este tipo de algoritmo para generar la estructura de directorios:
12345
->000000012345.jpg
000000012345
->000/000/012
123
es000/000/012/00000000012345.jpg
12345678901234
la ruta sería123/456/789/12345678901234.jpg
Algunas cosas a considerar sobre las estructuras de directorios y el almacenamiento de archivos:
fuente
Voy a poner mis 2 centavos en un consejo negativo: no vaya 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 concierto), a menudo modificados, múltiples versiones del archivo, a las que se accede con bastante frecuencia. Los problemas de la base de datos con los que se encuentran almacenados los archivos grandes son extremadamente tediosos, los problemas de escritura y transacción son complicados y se topan con problemas de bloqueo que pueden causar grandes accidentes de tren. Tengo más práctica dbcc en escribir guiones, y la restauración de las tablas de copias de seguridad que cualquier persona normal debe siempre 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 dependían de las bases de datos para nada más que la indexación. Los sistemas de archivos están diseñados para soportar 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.
fuente
Creo que la mayoría de los sitios que tienen que lidiar con esto usan algún tipo de hash para asegurarse de que los archivos se distribuyan uniformemente en las carpetas.
Digamos que tiene un hash de un archivo que es algo como esto
515d7eab9c29349e0cde90381ee8f810
. Podría tener esto almacenado en la siguiente ubicación y puede usar cuántos niveles de profundidad necesita para mantener baja la cantidad de archivos en cada carpeta.
\51\5d\7e\ab\9c\29\349e0cde90381ee8f810.jpg
He visto este enfoque tomado muchas veces. Todavía necesita una base de datos para asignar estos hashes de archivos a un nombre legible por humanos y cualquier otro metadato que necesite almacenar. Pero este enfoque escala bastante bien porque puede comenzar a distribuir el espacio de direcciones hash entre múltiples computadoras y / o grupos de almacenamiento, etc.
fuente
Idealmente, debe ejecutar algunas pruebas en tiempos de acceso aleatorio para varias estructuras, ya que la configuración específica del disco duro, el almacenamiento en caché, la memoria disponible, etc. pueden cambiar estos resultados.
Suponiendo que tenga control sobre los nombres de archivo, los dividiría al nivel de 1000 por directorio. Cuantos más niveles de directorio agregue, más inodos quemará, por lo que aquí hay un push-pull.
P.ej,
/ root / [0-99] / [0-99] / filename
Tenga en cuenta que 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 grandes cantidades 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 largos son similares".
También debe buscar deshabilitar las funciones del sistema de archivos que no necesita (por ejemplo, último tiempo de acceso). http://www.pctools.com/guides/registry/detail/50/
fuente
Hagas lo que hagas, no los guardes en un solo directorio.
Dependiendo de la distribución de los nombres de estas imágenes, puede crear una estructura de directorio donde tenga carpetas de nivel superior de una sola letra donde tendría otro conjunto de subcarpetas para la segunda letra de 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 mejor de esta solución es que la estructura de directorios actúa efectivamente como una tabla hash / diccionario. Dado un nombre de archivo de imagen, conocerá su directorio y, dado un directorio, conocerá un subconjunto de imágenes que van allí.
fuente
Los almacenaría en el sistema de archivos, pero depende de qué tan rápido crezca el número de archivos. ¿Estos archivos están alojados en la web? ¿Cuántos usuarios accederían a este archivo? Estas son las preguntas que deben responderse antes de que pueda darle una mejor recomendación. También miraría a Haystack de Facebook, tienen una muy buena solución para almacenar y servir imágenes.
Además, si elige el sistema de archivos, necesitará particionar estos archivos con directorios. Estuve analizando 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 .
fuente
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 usando un sistema de nombres inversos, donde los nombres de las carpetas se generan a partir del último dígito del archivo, last-1, etc. por ejemplo: 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 de manera uniforme toda la estructura de directorios.
fuente
Punto rápido, no necesita almacenar una ruta de archivo en su base de datos. Simplemente puede almacenar un valor numérico, si sus archivos se nombran de la manera que usted describe. Luego, utilizando uno de los esquemas de almacenamiento bien definidos ya discutidos, puede obtener el índice como un número y encontrar rápidamente el archivo atravesando la estructura del directorio.
fuente
El nuevo MS SQL 2008 tiene una nueva característica para manejar tales casos, se llama FILESTREAM. Echar un vistazo:
Descripción general de Microsoft TechNet FILESTREAM
fuente
¿Deberán nombrarse sus imágenes de forma única? ¿Puede el proceso que genera estas imágenes producir el mismo nombre de archivo más de una vez? Es difícil de decir sin saber qué dispositivo está creando el nombre de archivo, pero diga que el dispositivo se 'reinicia' y al reiniciar comienza a nombrar las imágenes como lo hizo la última vez que se 'reinició', si eso es una preocupación.
Además, dices que alcanzarás 1 millón de imágenes en un mes. ¿Qué tal después de eso? ¿Qué tan rápido continuarán estas imágenes llenando el sistema de archivos? ¿Se completarán en algún momento y se nivelarán en aproximadamente 1 millón de imágenes TOTALES o continuará creciendo y creciendo, mes tras mes?
Le pregunto porque podría comenzar a diseñar su sistema de archivos por mes, luego por imagen. Podría inclinarme a sugerir que almacene las imágenes en dicha estructura de directorio:
Mes, año, incluso día es bueno para imágenes de tipo de seguridad. No estoy seguro de si esto es lo que está haciendo, pero lo hice con una cámara de seguridad doméstica que tomaba una foto cada 10 segundos ... De esta manera, su aplicación puede profundizar en un tiempo específico o incluso en un rango donde podría pensar que se generó la imagen . O, en lugar de año, mes, ¿hay algún otro "significado" que pueda derivarse del archivo de imagen en sí? ¿Algunos otros descriptores, además del ejemplo de fecha que di?
No almacenaría los datos binarios en la base de datos. Nunca tuve un buen rendimiento / suerte con ese tipo de cosas. No puedo imaginar que funcione bien con 1 millón de imágenes. Almacenaría el nombre del archivo y eso es todo. Si todos van a ser JPG, entonces ni siquiera almacene la extensión. Crearía una tabla de control que almacenara un puntero al servidor del archivo, la unidad, la ruta, etc. De esta manera, puede mover esas imágenes a otro cuadro y aún así ubicarlas. ¿Necesita etiquetar con palabras clave sus imágenes? Si es así, querrá crear las tablas apropiadas que permitan ese tipo de etiquetado.
Usted / otros pueden haber abordado estas ideas mientras respondía ... Espero que esto ayude ...
fuente
Estoy involucrado en un proyecto que almacena 8.4 millones de imágenes en el transcurso de un año para documentar el estado de varios dispositivos. Se accede con mayor frecuencia a las imágenes más recientes, y rara vez se buscan imágenes más antiguas a menos que se descubra una condición que motivó a alguien a profundizar en los archivos.
Mi solución, basada en este uso, fue comprimir gradualmente las imágenes en archivos comprimidos. Las imágenes son JPG, cada una de aproximadamente 20kB y no se comprimen mucho, por lo que el esquema de compresión ZIP no es ninguno. Esto se hace simplemente para concatenarlos en una entrada de sistema de archivos que ayuda enormemente a NTFS en términos de velocidad cuando se trata de moverlos de una unidad a otra, o mirar a través de la lista de archivos.
Las imágenes de más de un día se combinan en un zip "diario"; las cremalleras de más de un mes se combinan en su respectiva cremallera "mensual"; y finalmente ya no se necesita nada más de un año y, en consecuencia, se elimina.
Este sistema funciona bien porque los usuarios pueden explorar los archivos (ya sea a través del sistema operativo o de una serie de aplicaciones cliente) y todo se nombra en función de los nombres de los dispositivos y las marcas de tiempo. En general, un usuario conoce estas dos piezas de información y puede localizar rápidamente cualquiera de los millones de imágenes.
Entiendo que esto probablemente no esté relacionado con sus detalles particulares, pero pensé en compartirlo.
fuente
Tal vez un esquema de nomenclatura basado en la fecha de creación, ya sea que incluya toda la información en el nombre del archivo o (mejor para navegar más tarde) dividiéndolo en directorios. Puedo pensar en lo siguiente, dependiendo de la frecuencia con la que generes imágenes:
Year/Month/Day/Hour_Minute_Second.png
Year/Month/Day_Hour_Minute_Second.png
etc. Entiendes mi punto ... =)
fuente
Year/Month/Day/Hour/Minute
: decida cuántos niveles de carpetas necesita según la frecuencia con la que se generan las imágenes cuando la velocidad es más alta , y luego no cree carpetas que se dejarían vacías.Me inclinaría a crear una estructura de carpetas basada en la fecha, por ejemplo, \ año \ mes \ día, y usar marcas de tiempo para los nombres de archivo. Si es necesario, las marcas de tiempo pueden tener un componente de contador adicional si las imágenes se van a crear tan rápido que puede haber más de una en un milisegundo. Al utilizar una secuencia más significativa a menos significativa para la clasificación de nombres, la búsqueda y el mantenimiento son muy sencillos. por ejemplo, hhmmssmm [seq] .jpg
fuente
¿Está considerando la recuperación ante desastres?
Algunas de las soluciones propuestas aquí terminan alterando el nombre del archivo (de modo que si el archivo físico se moviera, perdería la pista de qué archivo es realmente). Recomiendo mantener un nombre de archivo físico único para que si su lista maestra de ubicaciones de archivos se corrompe, pueda regenerarla con un pequeño shell, er, powershell, script;)
Por lo que leí aquí, parece que todos estos archivos se almacenarían en un sistema de archivos. Considere almacenarlos en múltiples sistemas de archivos en múltiples máquinas. Si tiene los recursos, determine un sistema de almacenamiento de cada archivo en dos máquinas diferentes en caso de que pierda una fuente de alimentación y el reemplazo esté dentro de 2 días.
Considere qué tipo de procedimientos necesitaría crear para migrar archivos entre máquinas o sistemas de archivos. La capacidad de hacer esto con su sistema en vivo y en línea puede ahorrarle un dolor de cabeza considerable en el futuro.
Puede considerar usar un GUID como nombre de archivo físico en lugar de un número incremental en caso de que su contador de número incremental (¿la columna de identidad de la base de datos?) Se estropee.
Si corresponde, considere usar un CDN como Amazon S3.
fuente
Si bien no he publicado imágenes en esa escala, anteriormente he escrito una pequeña aplicación de galería para servir ~ 25k imágenes en una máquina w de 400MHz. 512 MB de RAM más o menos. Algunas experiencias;
Evite las bases de datos relacionales a toda costa; Si bien las bases de datos, sin duda, son inteligentes en el manejo de datos, no están diseñadas para tal uso (obtuvimos bases de datos de valores clave jerárquicos especializados para los llamados sistemas de archivos ). Si bien no tengo más que una corazonada, apostaría a que el caché de DB se salga por la ventana, si le arrojas gotas realmente grandes. Si bien mi hardware disponible estaba en el extremo pequeño, no tocar la base de datos en absoluto en la búsqueda de imágenes dio órdenes de magnitud mejor velocidad.
Investigue cómo se comporta el sistema de archivos; en ext3 (o era ext2 en ese momento, no recuerdo), el límite de poder buscar eficientemente subdirectorios y archivos estaba alrededor de la marca de 256; así que solo tengo esa cantidad de archivos y carpetas en cualquier carpeta. De nuevo, notable aceleración. Si bien no sé sobre NTFS, cosas como XFS (que usa B-trees, por lo que recuerdo) es extremadamente rápido, simplemente porque pueden hacer búsquedas extremadamente rápidas.
Distribuir datos de manera uniforme; cuando experimenté con lo anterior, traté de distribuir los datos de manera uniforme en todos los directorios (hice un MD5 de la URL y lo usé para los directorios;
/1a/2b/1a2b...f.jpg
). De esta forma, lleva más tiempo alcanzar el límite de rendimiento que exista (y la memoria caché del sistema de archivos se anula en conjuntos de datos tan grandes de todos modos). (por el contrario, es posible que desee ver dónde están los límites desde el principio; luego, desea arrojar todo en el primer directorio disponible.fuente
Podría llegar tarde al juego en esto. Pero una solución (si se ajusta a su caso de uso) podría ser el hash de nombre de archivo. Es una forma de crear una ruta de archivo fácilmente reproducible utilizando el nombre del archivo y al mismo tiempo crear una estructura de directorio bien distribuida. Por ejemplo, puede usar los bytes del código hash del nombre de archivo como su ruta:
Esto daría como resultado que la ruta sea:
Luego puede encontrar
cat.gif
en la estructura del directorio reproduciendo el algoritmo.Usar HEX como nombres de directorio sería tan fácil como convertir los
int
valores:Resultando en:
Escribí un artículo sobre esto hace unos años y recientemente lo mudé a Medium. Tiene algunos detalles más y un código de muestra: Hashing de nombre de archivo: creación de una estructura de directorio hash . ¡Espero que esto ayude!
fuente
Si está en Windows, ¿qué tal en un sistema de archivos exFat?
http://msdn.microsoft.com/en-us/library/aa914353.aspx
Fue diseñado con el almacenamiento de archivos multimedia en mente, y disponible ahora.
fuente
Si TODOS no son necesarios de inmediato y puede generarlos sobre la marcha y estas son imágenes pequeñas, ¿por qué no implementar una memoria LRU o caché de disco sobre su generador de imágenes?
Esto podría salvarlo del almacenamiento y mantener las imágenes calientes que se servirán desde mem?
fuente
Acabo de ejecutar una prueba en zfs porque me encanta zfs, y tenía una partición de 500 gig en la que tenía compresión. Escribí un script que generó 50-100k archivos y los coloqué en directorios anidados 1/2/3/4/5/6/7/8 (5-8 niveles de profundidad) y lo dejé correr durante 1 semana. (no fue un gran script). Llenó el disco y terminó teniendo aproximadamente 25 millones de archivos más o menos. El acceso a cualquier archivo con una ruta conocida fue instantáneo. Listado de cualquier directorio con una ruta conocida fue instantánea.
Sin embargo, obtener un recuento de la lista de archivos (a través de buscar) tomó 68 horas.
También ejecuté una prueba poniendo muchos archivos en un directorio. Obtuve alrededor de 3.7 millones de archivos en un directorio antes de detenerme. Listado del directorio para obtener un recuento tomó alrededor de 5 minutos. Eliminar todos los archivos en ese directorio tomó 20 horas. Pero la búsqueda y el acceso a cualquier archivo fue instantáneo.
fuente
Veo que otros mencionan una base de datos, pero no veo ninguna mención de eso en su publicación. En cualquier caso, mi opinión sobre este punto en particular es: adherirse a una base de datos o sistema de archivos. Si tiene que mezclar los dos, tenga cuidado al respecto. Las cosas se ponen más complicadas. Pero es posible que tengas que hacerlo. Almacenar un millón de fotos en una base de datos no parece la mejor idea.
Es posible que le interese la siguiente especificación, la mayoría de las cámaras digitales la siguen para administrar el almacenamiento de archivos: https://en.wikipedia.org/wiki/Camera_Image_File_Format
Esencialmente, se crea una carpeta, como
000OLYMPUS
y se agregan fotos a esa carpeta (por ejemploDSC0000.RAW
). Cuando el contador de nombre de archivo alcanzaDSC9999.RAW
una nueva carpeta se crea (001OLYMPUS
) y la imagen se agrega nuevamente, restableciendo el contador, posiblemente con un prefijo diferente (ejP_0000.RAW
.:).Alternativamente, también podría crear carpetas basadas en partes del nombre del archivo (ya mencionado varias veces). Por ejemplo, si su foto tiene nombre
IMG_A83743.JPG
, guárdela enIMG_\A8\3\IMG_A83743.JPG
. Es más complicado de implementar, pero hará que sus archivos sean más fáciles de encontrar.Dependiendo del sistema de archivos (esto requerirá un poco de investigación), es posible que pueda volcar todas las imágenes en una sola carpeta, pero, en mi experiencia, esto generalmente causaría problemas de rendimiento.
fuente
Es posible que desee ver ZFS (sistema de archivos, administrador de volúmenes de Sun) Saludos
fuente
¡Una manera limpia de generar el camino a partir de un gran número es convertirlo fácilmente en hexadecimal y luego dividirlo!
por ejemplo
1099496034834
>0xFFFF1212
>FF/FF/12/12
Almacenar y cargar:
Códigos fuente completos: https://github.com/acrobit/AcroFS
fuente
Desafortunadamente, los sistemas de archivos son muy malos (rendimiento con muchos archivos por directorio o árboles de directorios profundos, comprobación de tiempos de reinicio, confiabilidad) en la administración de muchos archivos pequeños, por lo que la solución anterior que involucra archivos ZIP es mejor si desea usar un sistema de archivos.
Usar un administrador de base de datos es, con mucho, la mejor opción; uno simple como BDB o GDBM por ejemplo; Incluso un DBMS relacional como MySQL sería mejor. Solo las personas perezosas que no entienden los sistemas de archivos y las bases de datos (por ejemplo, aquellos que descartan las transacciones) tienden a utilizar los sistemas de archivos como bases de datos (o algo más raro, viceversa).
fuente
¿Qué tal una base de datos con una tabla que contiene una ID y un BLOB para almacenar la imagen? Luego, puede agregar nuevas tablas cada vez que desee asociar más elementos de datos con una foto.
Si espera escalar, ¿por qué no escalar ahora? Ahorrará tiempo tanto ahora como luego en la OMI. Implemente la capa de base de datos una vez, lo cual es bastante fácil de comenzar. O implemente algo con carpetas y nombres de archivo y bla, bla, bla, y luego cambie a otra cosa cuando comience a volar MAX_PATH.
fuente