Actualmente estoy creando una aplicación web que permite a los usuarios almacenar y compartir archivos, de 1 MB a 10 MB de tamaño.
Me parece que almacenar los archivos en una base de datos ralentizará significativamente el acceso a la base de datos.
¿Es esta una preocupación valida? ¿Es mejor almacenar los archivos en el sistema de archivos y guardar el nombre y la ruta del archivo en la base de datos? ¿Existen mejores prácticas relacionadas con el almacenamiento de archivos cuando se trabaja con una base de datos?
Estoy trabajando en PHP y MySQL para este proyecto, pero es el mismo problema para la mayoría de los entornos ( Ruby on Rails , PHP , .NET ) y bases de datos (MySQL, PostgreSQL ).
database
database-design
mysql
file-handling
B Seven
fuente
fuente
10MB
tan grande en un sistema moderno.Respuestas:
Razones a favor de almacenar archivos en la base de datos:
Motivo contra el almacenamiento de archivos en la base de datos:
FILESTREAM
objeto de SQL Server y necesita migrar a un sistema de base de datos diferente.En mi opinión, considerar el almacenamiento de archivos en la base de datos o no como "malo" requiere más información sobre las circunstancias y los requisitos. ¿El tamaño y / o el número de archivos siempre serán pequeños? ¿No hay planes para usar el almacenamiento en la nube? ¿Se entregarán los archivos en un sitio web o en un ejecutable binario como una aplicación de Windows?
En general, mi experiencia ha encontrado que almacenar rutas es menos costoso para la empresa, incluso teniendo en cuenta la falta de ACID y la posibilidad de huérfanos. Sin embargo, eso no significa que Internet no sea una legión con historias de falta de control de ACID que va mal con el almacenamiento de archivos, pero sí significa que, en general, esa solución es más fácil de construir, comprender y mantener.
fuente
En muchos casos, esta es una mala idea. Hinchará los archivos de la base de datos y causará varios problemas de rendimiento. Si pega los blobs en una tabla con una gran cantidad de columnas, es aún peor.
¡Sin embargo! Algunas bases de datos, como SQL Server, tienen un tipo de columna FILESTREAM. En este caso, sus datos se almacenan en un archivo separado en el servidor de la base de datos y solo se guarda en la tabla una ID del archivo. En este caso, no veo muchas razones para no mantener los datos en el servidor SQL. Los archivos se incluyen automáticamente como parte de la copia de seguridad del servidor, y la base de datos y los archivos nunca están fuera de sincronización. El problema con la sugerencia de Tony de almacenar nombres de archivos es que la base de datos y el sistema de archivos pueden desincronizarse. La base de datos afirmará que existe un archivo cuando se haya eliminado en el disco. Si un proceso está modificando la base de datos y luego falla, los archivos y la base de datos no coincidirán (es decir, no ACID con archivos fuera de una base de datos).
fuente
Sí, es una mala práctica.
Impacto en el rendimiento de la base de datos:
SELECT
con cualquier columna BLOB, siempre tendrá acceso al disco, mientras que sin BLOB tiene la oportunidad de obtener datos directamente de la RAM (la base de datos de alto rendimiento se optimizará para adaptarse a las tablas en la RAM);Ventaja de velocidad: ¡ ninguna ! Si bien algunos sistemas de archivos más antiguos no manejarían bien los directorios con millones de archivos, los más modernos no tienen ningún problema y de hecho usan el mismo tipo de estructuras de datos que los BD (generalmente B-trees). Por ejemplo, ext4 (sistema de archivos predeterminado de Linux) usa Htree .
Conclusión: obstaculizará el rendimiento de su base de datos y no mejorará el rendimiento de recuperación de archivos.
Además, dado que está hablando de aplicaciones web, servir archivos estáticos directamente desde el sistema de archivos usando un servidor web moderno, lo que puede hacer
sendfile()
syscall es una tremenda mejora en el rendimiento. Por supuesto, esto no es posible si está recuperando archivos de DB. Considere, por ejemplo, este punto de referencia , que muestra a Ngnix haciendo 25K requisitos / s con 1000 conexiones simultáneas en una computadora portátil de gama baja. Ese tipo de carga freiría cualquier tipo de DB.fuente
Sería pragmático al respecto y seguiría el principio de "no optimizar aún". Haga la solución que tenga sentido en este momento, y una que tenga los recursos de desarrollo para implementar adecuadamente. Hay muchos problemas potenciales . Pero esos no necesariamente se convierten en problemas reales. Por ejemplo, probablemente no sería un problema si tienes 100 usuarios. Que podría ser un problema si usted tiene o 100.000 10.000.000 de usuarios. Pero en el último caso, debería haber una base para más recursos de desarrollo para hacer frente a todos los problemas.
Pero almacenar los datos en la base de datos lo alivia de tratar con otros problemas, por ejemplo, dónde deben almacenarse los archivos, cómo deben copiarse, etc. Dado que está escribiendo una aplicación web, sería una muy buena idea por razones de seguridad para asegurarse de que el proceso que aloja la aplicación no tenga acceso de escritura al sistema de archivos, por lo que debe configurar el servidor para que el proceso tenga acceso de lectura / escritura a la carpeta donde se almacenan los datos.
Yo personalmente elegiría almacenar los datos en la base de datos, pero asegúrese de que los BLOBS no se lean hasta que realmente se necesiten, es decir, no se ejecute "SELECT * FROM ..." en esas tablas que contienen blogs. Y me aseguraría de que el diseño facilite mover los datos de la base de datos al sistema de archivos, si tiene problemas de rendimiento. Por ejemplo, guarde la información del archivo en una tabla de archivos separada , manteniendo así la información del archivo lejos de otras entidades comerciales.
Suponiendo que tiene una clase de archivo para representar un archivo leído en la base de datos, el impacto de codificación de su posterior traslado será mínimo.
fuente
Microsoft lanzó un libro blanco sobre esto hace unos años. Se concentra en SqlServer, pero puede encontrar información interesante allí:
Una versión muy concisa de su conclusión es:
Le recomendaría que escriba algunas pruebas pequeñas para su caso de uso particular. Tenga en cuenta que debe tener cuidado con los efectos de almacenamiento en caché. (¡Me sorprendió la primera vez que obtuve velocidades de guardar en disco que parecían tener mayores rendimientos de lo que era físicamente posible!)
fuente
La vieja sabiduría convencional de almacenar archivos fuera de la base de datos podría dejar de mantenerse. Como cuestión de principio, favorecería la integridad sobre la velocidad, y con un DBMS moderno, puede tener ambos.
Tom Kyte parece estar de acuerdo :
fuente
Si.
Si sirve un archivo desde su sistema de archivos, su servidor web puede usar el código del kernel como sendfile () en BSD o Linux para copiar el archivo directamente al socket. Es muy rápido y muy eficiente.
Servir archivos fuera de la base de datos significa que tiene que copiar datos del disco del servidor de la base de datos a la memoria del servidor de la base de datos, luego de la memoria del servidor de db al puerto de red del servidor de db, luego de la red al proceso del servidor web, y luego nuevamente al conexión de red saliente.
A menos que tenga una buena razón para no hacerlo, siempre es mejor servir archivos estáticos desde el sistema de archivos.
fuente
El famoso Tom Kyte ha escrito que ellos (Oracle) están utilizando la base de datos Oracle como servidor de archivos y está funcionando perfectamente bien, incluso más rápido que el sistema de archivos normal, con plena transaccionalidad, sin pérdida de rendimiento y con una sola copia de seguridad.
Sí, pero tenga en cuenta que son los productores de Oracle DB, y para cualquier otro usuario hay problemas de costos. El uso de bases de datos comerciales como Oracle para el almacenamiento de archivos simplemente no es rentable.
Sin embargo, con PostgreSQL, por ejemplo, simplemente puede ejecutar otra instancia de base de datos solo para el almacenamiento de blobs. Entonces tiene soporte transaccional completo. Pero la transaccionalidad cuesta espacio DB. Existe la necesidad de una base de datos para almacenar múltiples instancias de blob para múltiples transacciones concurrentes. En PostgreSQL es lo más doloroso, ya que esta base de datos almacena los duplicados de blobs hechos para la transacción, incluso si ya no son necesarios, hasta que se complete el proceso VACUUM.
Con el almacenamiento del sistema de archivos, por otro lado, debe tener mucho cuidado cuando alguien modifica el archivo, porque la transacción puede revertirse y la copia del archivo debe mantenerse hasta que la versión anterior ya no sea visible.
En el sistema donde los archivos solo se agregan y eliminan, y el acceso transaccional a los archivos no es un problema, el almacenamiento del sistema de archivos será, en mi humilde opinión, la mejor opción.
fuente
Por lo general, es mejor almacenar BLOB grandes en una tabla separada y simplemente mantener una referencia de clave externa al BLOB en su tabla principal. De esa manera, aún puede recuperar el archivo de la base de datos (por lo que no necesita ningún código especial) y evitar los problemas que rodean las dependencias externas de la base de datos (mantener sincronizada la base de datos y el sistema de archivos, etc.), pero solo incurre en esa sobrecarga si te unes explícitamente a esa tabla (o haces una llamada por separado). 10 MB no es terriblemente grande, la mayoría de las bases de datos comerciales modernas no tendrán problemas. La única razón por la que almacenaría un archivo en el sistema de archivos es para reducir el ancho de banda de la base de datos. Si su base de datos va a barajar muchos de estos archivos, entonces es posible que deba dividir la carga de trabajo y solo almacenar un descriptor de archivo de algún tipo. Entonces puede tener una llamada separada para cargar el archivo desde otro servidor,
fuente
Puede encontrarse con algunos de estos problemas:
SELECT *
que implica la fila con el blob grande lleva mucho tiempo, incluso si no necesita el blob (por supuesto, debe hacer una selección específica, pero a veces las aplicaciones se escriben así)Por supuesto, también obtienes algunos beneficios:
Personalmente no lo hago, ya que encuentro los contras mucho más pesados que los profesionales. Pero como se indicó anteriormente, depende totalmente de su caso de uso y tal.
fuente
Algunos sistemas de gestión de contenido de Enterpirse, como SiteCore, están utilizando una base de datos para almacenar datos de página y otra base de datos para almacenar archivos. Están usando MS SQL Server.
fuente
Para una implementación práctica, esto es lo que puede interesarle:
Benifits:
Desventajas:
fuente