web-dev-qa-db-fra.com

Est-ce une mauvaise pratique de stocker des fichiers volumineux (10 Mo) dans une base de données?

Je crée actuellement une application Web qui permet aux utilisateurs de stocker et de partager des fichiers, de 1 Mo à 10 Mo.

Il me semble que le stockage des fichiers dans une base de données ralentira considérablement l'accès à la base de données.

Est-ce une préoccupation valable? Est-il préférable de stocker les fichiers dans le système de fichiers et d'enregistrer le nom et le chemin d'accès au fichier dans la base de données? Existe-t-il des meilleures pratiques concernant le stockage de fichiers lors de l'utilisation d'une base de données?

Je travaille dans PHP et MySQL pour ce projet, mais le problème est le même pour la plupart des environnements ( Ruby on Rails , PHP , . NET ) et les bases de données (MySQL, PostgreSQL ).

202
B Seven

Raisons en faveur du stockage des fichiers dans la base de données:

  1. Cohérence ACID, y compris la restauration d'une mise à jour qui est compliquée lorsque les fichiers sont stockés en dehors de la base de données. Cela ne doit pas être passé sous silence. Il peut être très utile de synchroniser les fichiers et la base de données et de pouvoir participer aux transactions.
  2. Les fichiers accompagnent la base de données et ne peuvent pas en être orphelins.
  3. Les sauvegardes incluent automatiquement les fichiers binaires.

Raison contre le stockage de fichiers dans la base de données:

  1. La taille d'un fichier binaire diffère selon les bases de données. Sur SQL Server, lorsque vous n'utilisez pas l'objet FILESTREAM, par exemple, il s'agit de 2 Go. Si les utilisateurs ont besoin de stocker des fichiers plus volumineux (comme par exemple un film), vous devez sauter à travers des cerceaux pour que cette magie se produise.
  2. Augmente la taille de la base de données. Un concept général que vous devez prendre à cœur: Le niveau de connaissances requis pour maintenir une base de données augmente proportionnellement à la taille de la base de données. C'est-à-dire, grand les bases de données sont plus compliquées à gérer que les petites bases de données. Le stockage des fichiers dans la base de données peut agrandir la base de données. Même si, disons, une sauvegarde complète quotidienne aurait suffi, avec une taille de base de données plus importante, vous ne pourrez peut-être plus le faire. Vous devrez peut-être envisager de placer les fichiers dans un groupe de fichiers différent (si la base de données le prend en charge), modifier les sauvegardes pour séparer la sauvegarde des données de la sauvegarde des fichiers, etc. Aucune de ces choses n'est impossible à apprendre, mais faites-le ajouter de la complexité à la maintenance, ce qui signifie des coûts pour l'entreprise. Les bases de données plus volumineuses consomment également plus de mémoire car elles essaient de mettre autant de données en mémoire que possible.
  3. La portabilité peut être un problème si vous utilisez des fonctionnalités spécifiques au système comme l'objet FILESTREAM de SQL Server et devez migrer vers un autre système de base de données.
  4. Le code qui écrit les fichiers dans la base de données peut être un problème. Une entreprise pour laquelle j'ai consulté il n'y a pas si longtemps, à un moment donné, a connecté un frontend Microsoft Access à son serveur de base de données et a utilisé la capacité d'Access pour télécharger "n'importe quoi" en utilisant son contrôle Ole Object. Plus tard, ils ont changé pour utiliser un contrôle différent qui dépendait toujours d'Ole. Beaucoup plus tard, quelqu'un a changé l'interface pour stocker le binaire brut. Extraire ces objets Ole était un nouveau niveau d'enfer. Lorsque vous stockez des fichiers sur le système de fichiers, aucune couche supplémentaire n'est impliquée pour envelopper/modifier/modifier le fichier source.
  5. Il est plus compliqué de diffuser les fichiers sur un site Web. Pour le faire avec des colonnes binaires, vous devez écrire un gestionnaire pour diffuser le fichier binaire à partir de la base de données. Vous pouvez également le faire même si vous stockez des chemins d'accès aux fichiers mais que vous n'avez pas pour le faire. Encore une fois, l'ajout d'un gestionnaire n'est pas impossible mais ajoute de la complexité et constitue un autre point d'échec.
  6. Vous ne pouvez pas profiter du stockage cloud. Supposons qu'un jour vous souhaitiez stocker vos fichiers dans un compartiment Amazon S3. Si ce que vous stockez dans la base de données sont des chemins de fichier, vous avez la possibilité de les changer en chemins à S3. Pour autant que je sache, cela n'est possible dans aucun scénario avec aucun SGBD.

OMI, jugeant le stockage des fichiers dans la base de données ou non comme "mauvais" nécessite plus d'informations sur les circonstances et les exigences. La taille et/ou le nombre de fichiers seront-ils toujours petits? N'est-il pas prévu d'utiliser le stockage cloud? Les fichiers seront-ils servis sur un site Web ou un exécutable binaire comme une application Windows?

En général, mon expérience a montré que le stockage des chemins est moins coûteux pour l'entreprise, même en tenant compte du manque d'ACID et de la possibilité d'orphelins. Cependant, cela ne signifie pas qu'Internet n'est pas légion avec des histoires de manque de contrôle ACID qui vont mal avec le stockage de fichiers, mais cela signifie qu'en général, cette solution est plus facile à construire, à comprendre et à maintenir.

145
Thomas

Dans de nombreux cas, c'est une mauvaise idée. Cela gonflera les fichiers de la base de données et provoquera plusieurs problèmes de performances. Si vous collez les blobs dans un tableau avec un grand nombre de colonnes, c'est encore pire.

Toutefois! Certaines bases de données, comme SQL Server ont un type de colonne FILESTREAM. Dans ce cas, vos données sont réellement stockées dans un fichier séparé sur le serveur de base de données et seul un ID du fichier est enregistré dans la table. Dans ce cas, je ne vois pas beaucoup de raisons de ne pas conserver les données sur le serveur SQL. Les fichiers sont automatiquement inclus dans le cadre de la sauvegarde du serveur, et la base de données et les fichiers ne sont jamais désynchronisés. Le problème avec la suggestion de Tony de stocker les noms de fichiers, c'est que la base de données et le système de fichiers peuvent se désynchroniser. La base de données prétendra qu'un fichier existe lorsqu'il a été supprimé sur le disque. Si un processus modifie la base de données puis se bloque, les fichiers et la base de données ne correspondront pas (c.-à-d. Pas ACIDE avec des fichiers en dehors d'une base de données).

93

Oui, c'est une mauvaise pratique.

Impact sur les performances de la base de données:

  • si vous faites un SELECT avec n'importe quelle colonne BLOB, vous effectuerez toujours un accès au disque, tandis que sans BLOB vous aurez une chance d'obtenir des données directement de RAM (la base de données à haut débit sera optimisée pour tenir les tables dans la RAM);
  • la réplication sera lente, le délai de réplication élevé, car il devra envoyer BLOB aux esclaves. Un délai de réplication élevé entraînera toutes sortes de conditions de concurrence et d'autres problèmes de synchronisation, sauf si vous en tenez explicitement compte;
  • Les sauvegardes/restaurations de bases de données prendront beaucoup plus de temps;

Avantage de vitesse - aucun ! Bien que certains systèmes de fichiers plus anciens ne gèrent pas bien les répertoires contenant des millions de fichiers, la plupart des systèmes modernes n'ont aucun problème du tout et utilisent en fait le même type de structures de données que les BD (généralement des arbres B). Par exemple, ext4 (système de fichiers Linux par défaut) utilise Htree .

Conclusion: cela gênera les performances de votre base de données et n'améliorera pas les performances de récupération des fichiers.

De plus, puisque vous parlez d'application Web - servir des fichiers statiques directement à partir d'un système de fichiers en utilisant un serveur Web moderne, ce qui peut faire sendfile() syscall est énorme amélioration des performances. Ce n'est bien sûr pas possible si vous récupérez des fichiers à partir de DB. Considérons par exemple cette référence , montrant Ngnix effectuant 25 000 requêtes/s avec 1000 connexions simultanées sur un ordinateur portable bas de gamme. Ce type de charge ferait frire n'importe quel type de DB.

36
vartec

Je serais pragmatique à ce sujet et je suivrais le principe "ne pas encore optimiser". Faites la solution qui a du sens pour le moment, et celle que vous avez les ressources de développement pour mettre en œuvre correctement. Il y a beaucoup de problèmes potentiels. Mais ceux-ci ne deviennent pas nécessairement de vrais problèmes. Par exemple. Ce ne serait probablement pas un problème si vous avez 100 utilisateurs. Cela pourrait être un problème si vous avez 100 000 ou 10 000 000 d'utilisateurs. Mais dans ce dernier cas, il devrait y avoir une base pour plus de ressources de développement pour traiter tous les problèmes.

Mais le stockage des données dans la base de données vous évite de traiter d'autres problèmes, par exemple où les fichiers doivent-ils être stockés, comment doivent-ils être sauvegardés, etc. Puisque vous écrivez une application Web, ce serait une très bonne idée pour des raisons de sécurité de s'assurer que le processus hébergeant l'application n'a pas accès en écriture au fichier. système, vous devez donc configurer le serveur afin que le processus ait un accès en lecture/écriture au dossier où les données sont stockées.

Je choisirais personnellement de stocker les données dans la base de données, mais assurez-vous que les BLOBS ne sont pas lus jusqu'à ce qu'ils soient vraiment nécessaires, c'est-à-dire qu'aucun "SELECT * FROM ..." ne soit exécuté sur ces tables contenant des blogs. Et je m'assurerais que la conception facilite le déplacement des données de la base de données vers le système de fichiers si vous rencontrez des problèmes de performances. Par exemple, stockez les informations du fichier dans une table séparée Fichier , gardant ainsi les informations du fichier à l'écart des autres entités commerciales.

En supposant que vous ayez une classe File pour représenter un fichier lu dans la base de données, l'impact du codage de son déplacement ultérieur sera minime.

21
Pete

Microsoft a publié un livre blanc à ce sujet il y a quelques années. Il se concentre sur SqlServer, mais vous pouvez y trouver des informations intéressantes:

Vers BLOB ou pas vers BLOB? Stockage de gros objets dans une base de données ou un système de fichiers?

Une version très concise de leur conclusion est:

Lorsque vous comparez le système de fichiers NTFS et SQL Server 2005, les BLOBS inférieurs à 256 Ko sont gérés plus efficacement par SQL Server, tandis que NTFS est plus efficace pour les BLOBS supérieurs à 1 Mo.

Je vous recommande d'écrire quelques petits tests pour votre cas d'utilisation particulier. Gardez à l'esprit que vous devez vous méfier des effets de mise en cache. (J'ai été étonné la première fois que j'ai obtenu des vitesses de sauvegarde sur disque qui semblaient avoir des débits plus élevés que ce qui était physiquement possible!)

16
Benjol

La vieille sagesse conventionnelle de stocker des fichiers en dehors de la base de données pourrait ne plus être valable. Par principe, je préférerais l'intégrité à la vitesse, et avec un SGBD moderne, vous pouvez avoir les deux.

Tom Kyte semble d'accord :

Je ne connais aucun avantage à stocker des données que je souhaite conserver longtemps en dehors d'une base de données.

S'il est dans la base de données, je peux

assurez-vous qu'il est géré de manière professionnelle

sauvegardé

récupérable (avec le reste des données)

sécurisé

évolutif (essayez de mettre 100 000 documents dans un seul répertoire, maintenant, mettez-les dans le tableau - lequel "évolue" - ce n'est pas le répertoire)

Je peux récupérer (flashback) facilement

J'ai le verrouillage

J'ai lu la cohérence ...

11

Oui.

Si vous servez un fichier de votre système de fichiers, votre serveur Web peut utiliser le code du noyau comme sendfile () sur BSD ou Linux pour copier le fichier directement dans le socket. C'est très rapide et très efficace.

Servir des fichiers hors de la base de données signifie que vous devez copier les données du disque du serveur de base de données dans la mémoire du serveur de base de données, puis de la mémoire du serveur db vers le port réseau du serveur db, puis du réseau vers votre processus de serveur Web, puis de nouveau vers le connexion réseau sortante.

Sauf si vous avez une très bonne raison de ne pas le faire, il est toujours préférable de servir des fichiers statiques à partir du système de fichiers.

8
Evan P.

Le célèbre Tom Kyte a écrit qu'ils (l'Oracle) utilisent la base de données Oracle comme serveur de fichiers et que cela fonctionne parfaitement bien, encore plus rapidement qu'un système de fichiers normal, avec une transactionnalité complète, aucune perte de performances et une seule sauvegarde.

Oui, mais notez, ils sont le producteur de la base de données Oracle et pour tout autre utilisateur, il y a des problèmes de coût. L'utilisation de bases de données commerciales telles qu'Oracle pour le stockage de fichiers est tout simplement inefficace.

Cependant, avec PostgreSQL par exemple, vous pouvez simplement exécuter une autre instance de base de données uniquement pour le stockage d'objets blob. Vous disposez alors d'un support transactionnel complet. Mais la transactionnalité coûte de l'espace DB. Il est nécessaire que la base de données stocke plusieurs instances d'objets blob pour plusieurs transactions simultanées. Sur PostgreSQL, c'est le plus douloureux, car cette base de données stocke les doublons de blobs créés pour la transaction sont stockés même s'ils ne sont plus nécessaires, jusqu'à ce que le processus VACUUM soit terminé.

Avec le stockage du système de fichiers, en revanche, vous devez être très prudent lorsque quelqu'un modifie le fichier, car la transaction peut être annulée et la copie du fichier doit être conservée jusqu'à ce que l'ancienne version ne soit plus visible.

Dans le système où les fichiers sont uniquement ajoutés et supprimés et où l'accès transactionnel aux fichiers n'est pas un problème, le stockage du système de fichiers sera à mon humble avis le meilleur choix.

5
Danubian Sailor

Il est généralement préférable de stocker les BLOB de grande taille dans une table distincte et de simplement conserver une référence de clé étrangère au BLOB dans votre table principale. De cette façon, vous pouvez toujours récupérer le fichier à partir de la base de données (vous n'avez donc pas besoin de code spécial) et vous évitez les problèmes liés aux dépendances de base de données externes (en maintenant la base de données et le système de fichiers synchronisés, etc.), mais vous n'encourez que cette surcharge si vous vous joignez explicitement à cette table (ou effectuez un appel distinct). 10 Mo ne sont pas terriblement volumineux, la plupart des bases de données commerciales modernes n'auront pas de problème. La seule raison pour laquelle je stockerais un fichier dans le système de fichiers est de réduire la bande passante de la base de données. Si votre base de données va mélanger un grand nombre de ces fichiers, vous devrez peut-être fractionner la charge de travail et ne stocker qu'un descripteur de fichier quelconque. Ensuite, vous pouvez avoir un appel distinct pour charger le fichier à partir d'un autre serveur, de sorte que vous n'attachez pas vos connexions à la base de données (et les connexions réseau sur votre serveur de base de données) avec tous ces transferts de fichiers.

5
TMN

Vous pourriez rencontrer certains de ces problèmes:

  • Faire un SELECT * qui implique la ligne avec le gros blob prend très longtemps, même si vous n'avez pas besoin du blob (bien sûr, vous devez faire une sélection spécifique, mais parfois les applications sont écrites comme ceci)
  • Faire une sauvegarde peut prendre beaucoup plus de temps. En fonction de vos besoins, vous devrez peut-être verrouiller vos tables pendant la durée de la sauvegarde, vous souhaiterez peut-être garder votre temps de sauvegarde bas
  • La restauration prendra également beaucoup plus de temps.
  • Si vous manquez d'espace, vous devez penser à un moyen (peut-être déplacer toute la base de données vers un nouveau serveur) pour résoudre ce problème. En stockant les fichiers sur le système de fichiers, vous pouvez toujours monter un autre disque dur et définir des liens logiciels.
  • La simple recherche dans un fichier pour le débogage ou d'autres informations n'est pas aussi simple. Cela inclut également les scripts qui peuvent ne pas avoir accès à la base de données mais qui ont besoin de certaines informations de divers fichiers.

Bien sûr, vous bénéficiez également de certains avantages:

  • Sauvegarde des données et des fichiers lorsqu'ils sont synchronisés
  • La suppression du fichier à l'insu de la base de données n'est pas possible
  • Vous n'avez pas besoin de lire le fichier depuis le disque mais vous pouvez le faire en une seule instruction SQL
  • Vous pouvez télécharger la base de données, inclure le vidage dans votre environnement de développement et avoir toutes les dépendances là

Personnellement je ne le fais pas car je trouve les inconvénients bien plus lourds que les pros. Mais comme indiqué ci-dessus, cela dépend totalement de votre cas d'utilisation et autres.

4
Sgoettschkes

Certains systèmes de gestion de contenu d'entreprise, comme SiteCore, utilisent une base de données pour stocker les données de page et une autre base de données pour stocker les fichiers. Ils utilisent MS SQL Server.

1
šljaker

Pour une mise en œuvre pratique, voici ce qui peut vous préoccuper:

Benifits:

  1. Tout le contenu du fichier est définitivement synchronisé avec votre table. Comme indiqué ci-dessus, la sauvegarde des données est totalement pratique car vous n'avez pas besoin de garder les données synchronisées avec le système de fichiers.
  2. Du codage, vous pouvez obtenir le contenu du fichier directement à partir d'une sélection SQL.
  3. À partir d'une requête, vous pouvez même filtrer le contenu du fichier ou sa taille explicitement à partir de l'instruction SQL.

Inconvénients:

  1. Par rapport à une base de données dont la structure est sémantiquement la même mais qui ne stocke pas le contenu du fichier, votre base de données a tendance à consommer radicalement plus de mémoire lors de la requête.
  2. La sauvegarde automatique peut entraîner des problèmes de performances, mais pas beaucoup. Imaginons que votre serveur de base de données sauvegarde des éléments toutes les 6 heures et que les bases de données que vous possédez stockent un fichier de 10 Mo par enregistrement. Ce scénario n'est pas ce que vous voulez.
1

C'est l'un de ces "Puis-je utiliser une lame de rasoir pour couper une pomme?" Oui, vous pouvez.

Devrais-tu? À qui le dire ...

Je suppose que lorsque vous vous trouvez dans la situation où votre outillage le permet ou est le seul outillage disponible (au moins pour obtenir ce délai). Par exemple, j'ai utilisé un tournevis plat pour retirer un type de boulon philips ... était-ce correct? était-ce le bon outil? C'était un mauvais choix?

La réponse à ce cas est: la base de données n'est pas censée stocker des fichiers ... chaque fois que vous le faites, c'est mal, de la même manière théoriquement, je n'aurais pas dû utiliser le tournevis plat pour retirer le boulon philips, car ce faisant, j'ai perdu l'avantage du tournevis Philips de ne pas se déplacer et d'endommager tout ce sur quoi je travaille (comme vous perdriez des avantages si vous utilisez une base de données comme solution de stockage de fichiers) ... pourtant j'ai correctement calculé le risque et tout s'est très bien passé.

si vous souhaitez bien faire les choses, vous devriez probablement utiliser git pour stocker vos fichiers et conserver les hachages git nécessaires dans votre base de données pour faire référence à la bonne version de fichier dont vous avez besoin ... de la même manière que j'ai pu accéder à mon outil boîte et obtenir le putain de tournevis philips ...

0
Ordiel