Quel est le meilleur endroit pour stocker des fichiers binaires liés aux données de votre base de données? Devrais-tu:
Les avantages de (1) sont (entre autres) que l'atomicité des transactions est préservée. Le coût est que vous pourriez augmenter considérablement les exigences de stockage (et de streaming/sauvegarde associées)
Le but de (3) est de préserver l'atomicité dans une certaine mesure - si vous pouvez faire en sorte que le système de fichiers sur lequel vous écrivez n'autorise pas la modification ou la suppression de fichiers, et ait toujours le hachage correct comme nom de fichier. L'idée serait d'écrire le fichier dans le système de fichiers avant d'autoriser l'insertion/mise à jour référençant le hachage - si cette transaction échoue après l'écriture du système de fichiers mais avant la DML de la base de données, c'est bien parce que le système de fichiers est "truqué" étant le référentiel de tous fichiers et hachages possibles - peu importe s'il y a des fichiers qui ne sont pas pointés vers (et vous pouvez les nettoyer périodiquement si vous faites attention)
ÉDITER:
Il semble que certains SGBDR couvrent cela de manière individuelle - je serais intéressé de savoir comment les autres le font - et en particulier dans une solution pour les postgres
Stocker dans la base de données avec un blob
Un inconvénient est qu'il rend vos fichiers de base de données assez volumineux et peut-être trop volumineux pour être sauvegardés avec votre configuration existante. Un avantage est l'intégrité et l'atomicité.
Stocker sur le système de fichiers avec un lien dans la base de données
J'ai rencontré des catastrophes si horribles en faisant cela, et cela me fait peur que les gens continuent de le suggérer. Certaines des catastrophes incluaient:
C:\
jusqu'au .doc
et toutes les versions de NT n'ont pas pu gérer les longs trajets.Stocker dans le système de fichiers mais renommer en un hachage du contenu et stocker le hachage dans la base de données
Le dernier endroit où j'ai travaillé l'a fait sur la base de mon explication des scénarios ci-dessus. Ils pensaient qu'il s'agissait d'un compromis entre l'incapacité de l'organisation à acquérir de l'expérience avec des bases de données volumineuses (tout ce qui dépassait environ 40 G était jugé "trop gros"), l'incapacité de l'entreprise à acheter de gros disques durs et l'impossibilité d'acheter un dos plus moderne. up solution, et la nécessité de s'éloigner des risques # 1 & # 3 que j'ai identifiés plus haut.
Mon opinion est que le stockage dans la base de données en tant qu'objet blob est une meilleure solution et plus évolutive dans un scénario multi-serveur, en particulier avec des problèmes de basculement et de disponibilité.
Numéro 1 pour l'intégrité complète des données. Utilisez les autres options si vous ne vous souciez pas de la qualité des données. C'est si simple.
La plupart des SGBDR ont de toute façon des optimisations pour le stockage des BLOB (par exemple, le flux de fichiers SQL Server)
Si vous optez pour Oracle, jetez un œil à dbfs et Secure Files.
Secure Files dit tout, gardez TOUTES vos données en sécurité dans la base de données. Il est organisé en lobes. Secure Files est une version modernisée de lobs, qui devrait être activée.
dbfs est un système de fichiers dans la base de données. Vous pouvez le monter comme un système de fichiers réseau, sur un hôte Linux. C'est vraiment puissant. Voir blog Il a également beaucoup d'options pour s'adapter à vos besoins spécifiques. Étant un dba, étant donné un système de fichiers (basé sur la base de données, monté sur Linux), j'ai créé une base de données Oracle sans aucun problème. (une base de données, stockée dans une ... base de données). Non pas que ce serait très utile mais cela montre la puissance.
Les autres avantages sont: la disponibilité, la sauvegarde, la récupération, toutes les lectures cohérentes avec les autres données relationnelles.
Parfois, la taille est donnée comme raison de ne pas stocker de documents dans la base de données. Ces données doivent probablement être sauvegardées de quelque manière que ce soit, ce n'est donc pas une bonne raison de ne pas les stocker dans la base de données. Surtout dans une situation où les anciens documents doivent être considérés comme en lecture seule, il est facile de faire de grandes parties de la base de données en lecture seule. Dans ce cas, ces parties de la base de données n'ont plus besoin d'une sauvegarde fréquente élevée.
Une référence dans une table à quelque chose en dehors de la base de données n'est pas sûre. Il peut être manipulé, est difficile à vérifier et peut facilement se perdre. Et les transactions? La base de données propose des solutions à tous ces problèmes. Avec Oracle DBFS, vous pouvez donner vos documents à des applications autres que des bases de données et ils ne sauraient même pas qu'ils piquent dans une base de données.
Dernière grande surprise, les performances d'un système de fichiers dbfs sont souvent meilleures que celles d'un système de fichiers classique. Cela est particulièrement vrai si les fichiers sont plus volumineux que quelques blocs.
Je pense que la bonne réponse ici dépend beaucoup de votre demande et de l'importance de ces documents.
Pour un système de gestion de documents, ou un système où la récupérabilité des documents stockés est critique (donc la plupart des choses financières, RH ou CRM), le stockage de documents en ligne ou l'utilisation de la technologie documentaire propriétaire de votre fournisseur de base de données préféré semble être la bonne chose à faire.
Cependant, il existe de nombreuses applications pour lesquelles je pense que la décision contraire est appropriée.
Les systèmes de helpdesk et les systèmes de type wiki sont ceux où je pense qu'il est très logique de conserver les données out de la base de données. Je pense que certains, comme Jira, offrent en fait une option pour choisir si vous souhaitez stocker les documents en ligne ou non.
Pour une entreprise de taille moyenne, le stockage de documents pour un système de billetterie en ligne peut faire la différence entre une sauvegarde compressée mesurée en mégaoctets et une mesurée en gigaoctets.
Personnellement, je préférerais remettre un système de billetterie en ligne dans quelques minutes et lutter avec les documents (généralement moins importants) pendant quelques heures, plutôt que d'augmenter mon RTO "il est cassé et le CTO respire dans mon cou" en ayant à restaurer et relisez les journaux à partir d'une sauvegarde beaucoup plus importante.
La séparation des documents présente d'autres avantages.
Je pense qu'une combinaison hybride de # 2 et # 3 pourrait être intelligente. Conservez les noms de fichiers d'origine, mais calculez et stockez un hachage/somme de contrôle du document, de sorte que vous ayez un point de référence qui facilitera la récupération si quelqu'un déplace ou renomme le fichier.
Le stockage des fichiers avec leurs noms de fichiers d'origine signifie que les applications peuvent littéralement les extraire directement d'un système de fichiers et les envoyer sur le câble, ou dans un monde client lourd, peut-être même diriger l'utilisateur directement vers le serveur de fichiers.
Ne le fais pas.
Il n'y a vraiment aucun avantage à avoir des fichiers stockés dans la base de données.
N'est-ce pas déjà bizarre et louche quand vous pensez à vous-même:
Dois-je stocker des fichiers dans une base de données ou un système de fichiers ?
Encore mieux, dites-le à voix haute.
Sur les faits:
" [~ # ~] pros [~ # ~] " ... mais pas tout à fait :
Je ne veux vraiment pas être partial mais je ne pense pas qu'il y ait plus à ajouter. Les pros ne sont pas vraiment géniaux si on y réfléchit.
Si j'ai oublié un commentaire ci-dessous, continuez à lire ci-dessous.
LES INCONVÉNIENTS:
AVANTAGES:
[~ # ~] contre [~ # ~] :
En ce moment, vous vous demandez, attendez, vous voulez dire qu'il n'y a pas de contre?! Comment venir?
Les plus grosses erreurs ici sont que les gens essaient de visser une vis avec un marteau.
La principale raison et j'irais jusqu'à dire seulement la raison pour laquelle cela est demandé est à cause des liens de fichiers .
Il s'agit d'un problème que la base de données n'est pas censée résoudre. Cela peut même paraître idiot si vous y pensez.
"La base de données résoudra mes problèmes de liaison de fichiers."
En réalité, logiquement l'application devrait en fait être en charge de la gestion et du service liens.
Cela éliminerait également les chemins natifs, rendrait l'application plus portable, maintenable et permettrait de basculer vers tout type de système de fichiers sans rien casser.
Quant à la façon de l'implémenter, cela dépasse le cadre de cette réponse, mais vous pouvez jeter un œil à un exemple général dans le langage Web sans doute le plus utilisé (PHP):
https://github.com/symfony/Routing
https://github.com/kriswallsmith/assetic
Les deux ensemble sont vraiment puissants.
Je veux ajouter mon expérience ici quant aux compromis. Dans PostgreSQL, au moins, les impacts sur les performances sont assez minimes en termes de serveur db. Les gros objets blob sont stockés dans des fichiers séparés, pas dans les tables de tas principales afin de les éloigner des opérations qui peuvent compter un grand nombre d'enregistrements. D'autres dbs peuvent faire quelque chose de similaire.
Le principal avantage est la possibilité de conserver toutes les données connexes en un seul endroit à des fins d'atomicité et de sauvegarde. Cela réduit considérablement les risques de problème.
L'inconvénient majeur n'est pas celui que j'ai vu ci-dessus, et c'est l'utilisation de la mémoire sur le front-end. Je ne sais pas exactement comment chaque base de données gère cela, donc cela peut dépendre de l'implémentation, mais pour PostgreSQL, les données arrivent sous la forme d'une chaîne d'échappement ASCII (éventuellement hexadécimale, éventuellement avec des échappements en ligne). doit ensuite être reconverti en binaire à l'avant. De nombreux frameworks que j'ai vus pour ce faire impliquent de passer la valeur (pas comme référence) puis de construire une nouvelle chaîne binaire basée sur elle. J'ai calculé qu'en utilisant Perl pour ce faire a fini par utiliser plusieurs fois la mémoire du binaire d'origine pour accomplir.
Verdict: si les fichiers ne sont consultés qu'occasionnellement, je les stocke dans la base de données. S'ils sont fréquemment et à plusieurs reprises consultés, au moins avec PostgreSQL, je pense que les coûts l'emportent sur les avantages.
Tout le monde, sans exception, qui peut exécuter n'importe quel SGBDR sur le marché possède déjà une base de données spécifiquement pour stocker des fichiers, et le SGBDR lui-même l'utilise! Cette base de données est le système de fichiers . Parlons maintenant de certains des inconvénients potentiels du stockage de fichiers dans la base de données, ainsi que de certains facteurs atténuants spécifiques pour le stockage de fichiers dans la base de données.
Non filehandes aux fichiers de la base de données. Qu'est-ce que cela signifie?
Programmeur-talk: Vous NE POUVEZ PAS chercher (fseek
), il n'y a pas de possibilité de gérer la ressource avec un accès asynchrone (asyncio
ou epoll
), il n'y a pas sendfile
(sauvegarde de la copie depuis l'espace noyau).
Application pratique: vous souhaitez envoyer une vidéo ou une image à un client via HTTP2/3? S'il se trouve dans la base de données, vous devrez d'abord l'interroger. Pour que la requête renvoie ce fichier, vous devrez attendre que la requête entière se termine avant que ce fichier puisse passer à l'étape suivante. Dans une installation de production avec un rdbms sur un serveur différent du serveur Web, vous devrez d'abord transférer le fichier entièrement du rdbms au serveur Web plutôt que de le diffuser en continu. Cependant, si la couche transport fournit une abstraction du système de fichiers (que même NFS prend en charge), vous pouvez rechercher à mi-chemin dans le fichier et commencer immédiatement à le retransmettre au client sans mettre en mémoire tampon le fichier plus que nécessaire. Cette opération est généralement effectuée par le serveur Web nginx , Apache , PureFTP et ProFTP.
Double copie sur le SGBDR. Du fait même qu'il se trouve dans la base de données, vous l'écrirez probablement deux fois. Une fois dans un journal d'écriture anticipée (WAL), puis à nouveau dans l'espace disque logique.
Aucune mise à jour, jamais MVCC signifie que rien n'est mis à jour, seulement copié à nouveau avec des modifications , puis l'ancienne ligne est marquée comme expirée (supprimée). Toute mise à jour du fichier nécessitera l'écriture de la ligne entière , pas seulement le fichier de la ligne entière. Les systèmes de fichiers peuvent également fournir cela, avec la journalisation des données, mais vous en avez rarement besoin.
Lecture et transfert de fichiers pour ralentir la requête Si le fichier lui-même est stocké sur une ligne que vous devez interroger, la ligne entière devra soit attendez que le fichier soit transféré, ou vous devrez émettre deux requêtes distinctes.
Utilisation de la mémoire sur le client DB. Le client DB (libpq, jdbc, odbc, freetds, etc.) ou similaire tamponnera probablement la requête en mémoire. Lorsque ce tampon en mémoire est épuisé, il peut démarrer un tampon de disque ou pire encore, il peut retomber sur le noyau pour être paginé sur le disque.
Limitation des requêtes de nombreuses bases de données offrent la possibilité de tuer et de récolter des requêtes lorsqu'elles prennent trop de temps ou de ressources. Gardez à l'esprit que les transferts de fichiers ne seront détaillés dans aucune implémentation. Cette requête a-t-elle été supprimée après 3 secondes? Ou cela a-t-il pris 1 seconde et le back-end a passé 2 secondes à transférer un fichier? Non seulement "détaillé", comment allez-vous indiquer efficacement le temps qu'une requête devrait prendre lorsque 99,9% des requêtes renvoient 1 Ko, et l'autre retourne 1 Go?
Pas de copie sur écriture ou déduplication XFS et BTRFS prennent en charge la copie sur écriture et la déduplication de manière transparente. Cela signifie qu'avoir la même image partout ou en avoir besoin d'une deuxième copie peut être transparent géré par le système de fichiers. Cependant, si le fichier n'est pas autonome et se trouve sur une ligne ou dans un magasin, le système de fichiers est probablement incapable de le dédupliquer.
Intégrité beaucoup de gens parlent ici d'intégrité. Selon vous, qu'est-ce qui est le mieux pour détecter la corruption du système de fichiers, une application qui utilise le système de fichiers ou les principaux utilitaires du système de fichiers? Stockez un fichier dans une rangée ou hors ligne et toute corruption du système de fichiers sera obscurcie la base de données. xfs_repair
est sacrément bon à récupérer lorsque vous avez une corruption du système de fichiers ou du disque dur, et s'il échoue, il sera toujours beaucoup plus facile de faire de la criminalistique des données.
Migration vers le cloud si jamais vous souhaitez stocker les fichiers sur un SAN ou le cloud, vous en aurez d'autant plus) difficulté car maintenant que la migration de stockage est une migration de base de données. Si vos fichiers sont par exemple stockés sur le système de fichiers, vous pouvez les déplacer assez facilement vers S3 (et avec quelque chose comme s3fs
il peut être transparent).
Le stockage de fichiers dans la base de données a quelques cas d'utilisation valides,
Certaines bases de données ont une notion de "ressource gérée en externe" où la base de données gère le fichier en privé sur le disque, comme
PostgreSQL via l'infrastructure Large Object fournit un descripteur de fichier à une ressource pour la durée de la transaction.
infrastructure filestream de SQL Server 2017 fournit un accès temporaire qui dure pendant la durée de la transaction que vous pouvez utiliser pour obtenir le chemin du fichier et ouvrir un descripteur de fichier.
Oracle fournit BFILE
(cela n'a rien à voir avec leur substance LOB interne qui s'appelle SecureFile
Certaines bases de données stockent de gros objets binaires hors ligne ou peuvent, comme Oracle SecureFile. Cela vous permet de mettre à jour la ligne, sans réécrire le fichier.
Certaines bases de données comme Oracle font leur MVC sans journal WAL et n'ont pas à doubler l'écriture du fichier.
Certaines bases de données, comme SQL Server et Oracle, permettent de "diffuser" des données à partir du fichier sans jamais avoir de descripteur de fichier. Cela peut ou non s'exécuter sur une connexion différente de la requête databaes. Mais la clé ici est que pendant que vous pouvez diffuser le fichier (en théorie), je ne trouve aucune preuve d'un produit non fabriqué par le fournisseur qui utilise cette fonctionnalité. Par exemple, où est le pont NGINX/Apache pour vous permettre de le faire?
Oracle fournit une déduplication, une compression et un chiffrement facultatifs via le stockage LOB interne (comme SecureFile).
Le pire des cas lorsque vous placez un fichier dans la base de données est très mauvais pour les performances et la compatibilité avec les outils. Cela dépend toujours exceptionnellement de l'implémentation. La base de données n'est en aucun cas meilleure pour être un système de fichiers que le système de fichiers. À tous égards, c'est un compromis et même lorsque vous obtenez de puissantes fonctionnalités d'atténuation (comme le cas de SecureFile), l'outillage est si pauvre qu'il n'est vraiment pas beaucoup plus qu'un point marketing à moins que votre pile entière ne soit construite par le fournisseur RDBMS.
Restez simple et la règle générale est de garder les fichiers hors de la base de données .
Comment devez-vous stocker des fichiers ou résumer un système de fichiers de cette manière pour fonctionner efficacement pour plusieurs locataires et utilisateurs? Je suis partisan du hachage du contenu du fichier. C'est assez courant de nos jours et ça marche bien.
À l'époque, Microsoft a accéléré la possibilité de stocker des images (et des types de données d'objets blob similaires) dans la base de données. C'était une nouvelle fonctionnalité intéressante de SQL Server 2000 (je suis sûr que c'était 2000, pas 7.0) et beaucoup de gens ont sauté dans le train.
Le stockage des BLOBS dans la base de données présente des avantages et des inconvénients:
D'une part, toutes vos données et images ou documents associés peuvent être stockés et accessibles en un seul endroit. L'utilisateur de l'application ne nécessite pas d'autorisations réseau spéciales, car c'est SQL qui sert les images/fichiers/documents.
D'un autre côté, votre base de données peut devenir assez volumineuse, selon la taille et le nombre de BLOBS que vous stockez. Cela affecte les sauvegardes, les exigences de stockage, les opérations de récupération sensibles au temps, etc.
SQL Server 2008 a introduit le streaming de fichiers. La base de données contient des pointeurs vers les fichiers, les fichiers ne résident pas sur le serveur, mais lorsque vous sauvegardez la base de données, les fichiers sont également sauvegardés.
Vos sauvegardes peuvent devenir assez volumineuses, mais vous ne vous retrouvez pas avec des fichiers/documents/blobs/images orphelins.
Ma préférence personnelle a été de laisser la base de données stocker des pointeurs/emplacements réseau et de laisser un serveur de fichiers gérer les fichiers. Les serveurs de fichiers sont de toute façon mieux optimisés pour ces tâches.
Mon vote serait pour ni l'un ni l'autre. Stockez les données dans un système comme Amazon S3 ou le CDN de Microsft et stockez cette URL dans la base de données.
De cette façon, vous obtenez la fiabilité d'avoir les données toujours accessibles sans avoir à gérer des bases de données de taille monstre.
Bien que cela dépende en partie de l'application/de l'environnement (personnes incluses), je choisirais le blob.
Tout garder dans la base de données signifie que la réplication fonctionne pour les données de fichier. Vous auriez besoin d'un mécanisme distinct pour synchroniser les fichiers FS.
Dans certaines applications, le système de fichiers ne doit de toute façon pas être modifié. Par exemple, sur un site Web de production, j'éviterais d'utiliser le système de fichiers pour toutes les données non jetables (le site vit sous SCM, les données dans une base de données).
En supposant que nous avons plusieurs utilisateurs/applications avec des autorisations distinctes, tout stockage de système de fichiers offre une possibilité de différences dans les droits d'accès DB et FS).
Le raffinement que j'envisagerais d'apporter au stockage BLOB est de fragmenter les données si cela a du sens; si vous n'avez besoin que de 512 octets à partir d'un BLOB de 20 Mo, cet accès de type secteur est une véritable aubaine, surtout si vous traitez avec des clients distants (et encore une fois, une mise à jour partielle crée beaucoup moins de trafic de réplication).
Pour les postgres:
C'est en fait tout droit devant. Il existe un type BYTEA
qui peut être utilisé pour stocker des chaînes binaires. Par défaut, il n'y a pas d'utilitaires intégrés comme ceux mentionnés pour MS ou Oracle. Ainsi, le stockage de nombreux fichiers volumineux et leur récupération peuvent devenir fastidieux. Vous devez également effectuer la conversion des fichiers dans l'application (comme avec un ByteStream
ou similaire, aucune idée de la façon dont cela fonctionne avec les solutions de base de données MS/Oracle file <-> spécifiques). Il existe également un type lo
, qui facilite le travail de gestion des BLOBs, car une partie de la gestion interne de ces types peut ne pas suivre les références.