Stocker un million d'images dans le système de fichiers


79

J'ai un projet qui va générer un grand nombre d'images. Environ 1.000.000 pour commencer. Ce ne sont pas de grandes images, je vais donc les stocker sur une seule machine au début.

Comment recommandez-vous de stocker ces images efficacement? (Système de fichiers NTFS actuellement)

J'envisage un schéma de nommage ... pour commencer, toutes les images auront un nom incrémental à partir de 1, j'espère que cela m'aidera à les trier plus tard si nécessaire, et à les jeter dans des dossiers différents.

Quel serait un meilleur schéma de nommage:

a / b / c / 0 ... z / z / z / 999

ou

a / b / c / 000 ... z / z / z / 999

une idée à ce sujet?


1
Sont-ils liés à des utilisateurs spécifiques ou simplement génériques? Sont-ils regroupés de quelque manière que ce soit?

seulement générique. un tas d'images générées par certains équipements techniques. Je les nomme progressivement à partir de 1 juste pour avoir l’idée d’une référence temporelle.
Samedi

Comment vont-ils être utilisés / consultés? via une application sur mesure ou quoi?
Dove


1
:)) oui ... 1 mil. images porno :))
s.mihai

Réponses:


73

Je vous recommande d'utiliser un système de fichiers standard au lieu de bases de données. L'utilisation du système de fichiers est plus simple qu'une base de données, vous pouvez utiliser des outils normaux pour accéder aux fichiers, les systèmes de fichiers sont conçus pour ce type d'utilisation, etc. NTFS devrait parfaitement fonctionner comme système de stockage.

Ne stockez pas le chemin d'accès réel à la base de données. Il est préférable de stocker le numéro de séquence de l’image dans la base de données et d’avoir une fonction capable de générer un chemin à partir du numéro de séquence. par exemple:

 File path = generatePathFromSequenceNumber(sequenceNumber);

Il est plus facile à gérer si vous devez modifier la structure des répertoires. Peut-être avez-vous besoin de déplacer les images vers un autre emplacement, peut-être que vous manquez d'espace et que vous commencez à stocker certaines images sur le disque A et d'autres sur le disque B, etc. Il est plus facile de changer une fonction que de changer les chemins d'accès dans la base de données .

J'utiliserais ce type d'algorithme pour générer la structure de répertoires:

  1. Premièrement, remplissez votre numéro de séquence avec des zéros au début jusqu'à ce que vous ayez au moins 12 caractères. Ceci est le nom de votre fichier. Vous voudrez peut-être ajouter un suffixe:
    • 12345 -> 000000012345.jpg
  2. Divisez ensuite la chaîne en blocs de 2 ou 3 caractères, chaque bloc désignant un niveau de répertoire. Avoir un nombre fixe de niveaux de répertoires (par exemple 3):
    • 000000012345 -> 000/000/012
  3. Stockez le fichier dans le répertoire généré:
    • Ainsi, le chemin complet et le nom du fichier pour le fichier avec l'ID de séquence 123est 000/000/012/00000000012345.jpg
    • Pour un fichier avec l'ID de séquence, 12345678901234le chemin serait123/456/789/12345678901234.jpg

Quelques éléments à prendre en compte concernant la structure des répertoires et le stockage des fichiers:

  • L'algorithme ci-dessus vous donne un système où chaque répertoire feuille contient au maximum 1000 fichiers (si vous avez moins de 1 000 000 000 000 fichiers au total)
  • Il peut y avoir des limites au nombre de fichiers et sous-répertoires qu'un répertoire peut contenir, par exemple , le système de fichiers ext3 sous Linux a une limite de 31998 sous-répertoires par répertoire.
  • Les outils normaux (WinZip, l'Explorateur Windows, la ligne de commande, le shell bash, etc.) risquent de ne pas très bien fonctionner si vous avez un grand nombre de fichiers par répertoire (> 1000).
  • La structure de répertoires elle-même prendra un peu d’espace disque, vous ne voudrez donc pas trop de répertoires.
  • Avec la structure ci-dessus, vous pouvez toujours trouver le chemin correct pour le fichier image en regardant simplement le nom du fichier, si vous endommagez la structure de votre répertoire.
  • Si vous devez accéder aux fichiers de plusieurs ordinateurs, envisagez de les partager via un système de fichiers réseau.
  • La structure de répertoire ci-dessus ne fonctionnera pas si vous supprimez beaucoup de fichiers. Il laisse des "trous" dans la structure de répertoires. Mais puisque vous ne supprimez aucun fichier, ça devrait aller.

1
très intéressant! diviser le nom du fichier ... je n'y avais pas pensé. Je suppose que c'est la façon élégante de le faire: -?
Samedi

37
L'utilisation d'un hachage (tel que MD5) comme nom du fichier, ainsi que la distribution du répertoire, fonctionneraient. L'intégrité des fichiers ne constitue pas seulement un avantage supplémentaire du schéma de dénomination (facile à vérifier), mais vous bénéficiez d'une distribution raisonnablement égale dans toute la hiérarchie des répertoires. Donc, si vous avez un fichier nommé "f6a5b1236dbba1647257cc4646308326.jpg", vous le stockerez dans "/ f / 6" (ou aussi profond que vous le souhaitez). 2 niveaux de profondeur donne 256 répertoires, soit un peu moins de 4000 fichiers par répertoire pour les fichiers initiaux de 1 m. Il serait également très facile d’automatiser la redistribution dans un schéma plus détaillé.

+1 Je viens de remarquer que cette réponse était similaire à celle que je viens de publier.
3dinfluence

1
Je suis tout à fait d’accord pour utiliser le système de fichiers et créer un identifiant artificiel pour "découper" les noms de dossiers. Mais vous devriez également essayer d'obtenir une distribution aléatoire d'identifiants, c'est-à-dire ne pas utiliser de numéro de séquence. Cela vous permettrait d'avoir une arborescence de dossiers plus équilibrée. De plus, avec une distribution aléatoire, vous pouvez plus facilement partitionner l'arborescence sur plusieurs systèmes de fichiers. J'utiliserais également un réseau SAN basé sur ZFS avec déduplication activée et un volume fragmenté pour chaque système de fichiers. Vous pouvez toujours utiliser NTFS en utilisant iSCSI pour accéder au réseau de stockage.
Michael Dillon

Si vous allez de droite à gauche à l'étape 2, les fichiers sont répartis de manière égale. Aussi, ne vous inquiétez pas du fait que vous ne remplissez pas suffisamment de zéros, vous aurez un nombre illimité de fichiers
ropo le

31

Je vais mettre mes 2 cents sur un conseil négatif: n'allez pas avec une base de données.

Je travaille avec des bases de données de stockage d’images depuis des années: fichiers volumineux (1 Mo -> 1 Go), souvent modifiés, multiples versions du fichier, auxquelles on accède assez souvent. Les problèmes de base de données liés au stockage de fichiers volumineux sont extrêmement fastidieux, les problèmes d’écriture et de transaction sont épineux et vous rencontrez des problèmes de verrouillage qui peuvent causer de graves épaves de train. J'ai plus de pratique dans l'écriture de scripts dbcc et dans la restauration de tables à partir de sauvegardes que n'importe quelle personne normale devrait en avoir.

La plupart des systèmes plus récents avec lesquels j'ai travaillé ont poussé le stockage de fichiers vers le système de fichiers et ne s'appuient que sur des bases de données pour l'indexation. Les systèmes de fichiers sont conçus pour supporter ce type d'abus, ils sont beaucoup plus faciles à développer et vous perdez rarement tout le système de fichiers si une entrée est corrompue.


Oui. note prise!
Samedi

5
Avez-vous examiné le type de données FILESTREAM de SQL 2008? C'est un croisement entre la base de données et le stockage du système de fichiers.
NotMe

Utilisez +1 pour coller au serveur de fichiers plutôt qu’à une base de données car vous effectuez des opérations d’E / S rapides et peu fréquentes.

Que se passe-t-il si vous ne stockez que quelques centaines de documents ou de photos par base de données - aucun inconvénient à utiliser une base de données pour le stockage?
Bip bip

1
+1 ... un système de fichiers est quand même une sorte de "base de données" (ntfs bien sûr), alors pourquoi le rendre trop compliqué.
Akira

12

Je pense que la plupart des sites qui traitent de ce problème utilisent un hachage pour s’assurer que les fichiers sont répartis de manière égale dans les dossiers.

Supposons que vous ayez un hachage de fichier qui ressemble à ceci. 515d7eab9c29349e0cde90381ee8f810
Vous pourriez l'avoir stocké à l'emplacement suivant et vous pouvez utiliser le nombre de niveaux dont vous avez besoin pour limiter le nombre de fichiers dans chaque dossier.
\51\5d\7e\ab\9c\29\349e0cde90381ee8f810.jpg

J'ai vu cette approche prise à plusieurs reprises. Vous avez toujours besoin d'une base de données pour mapper ces hachages de fichiers sur un nom lisible par l'homme et sur les métadonnées que vous avez besoin de stocker. Mais cette approche évolue assez bien parce que vous pouvez commencer à distribuer l’espace d’adresse de hachage entre plusieurs ordinateurs et / ou pools de stockage, etc.


2
Git utilise une approche similaire: git-scm.com/book/fr/v2/Git-Internals-Git-Objects (pour étayer cette réponse)
aexl

11

Idéalement, vous devez exécuter des tests sur des temps d'accès aléatoires pour différentes structures, car la configuration de votre disque dur, la mise en cache, la mémoire disponible, etc. peuvent modifier ces résultats.

En supposant que vous ayez le contrôle sur les noms de fichiers, je les partitionnerais au niveau de 1 000 par répertoire. Plus vous ajoutez de niveaux de répertoire, plus vous gravez d'inodes, il y a donc un push-pull ici.

Par exemple,

/ root / [0-99] / [0-99] / nom_fichier

Remarque: http://technet.microsoft.com/en-us/library/cc781134(WS.10).aspx contient plus de détails sur la configuration de NTFS. En particulier, "Si vous utilisez un grand nombre de fichiers dans un dossier NTFS (300 000 ou plus), désactivez la génération de noms de fichiers courts pour obtenir de meilleures performances, en particulier si les six premiers caractères des noms de fichiers longs sont similaires."

Vous devriez également chercher à désactiver les fonctionnalités de système de fichiers dont vous n’avez pas besoin (par exemple, la dernière heure d’accès). http://www.pctools.com/guides/registry/detail/50/


3
+1 pour désactiver la génération de nom de fichier 8.3 et l'heure du dernier accès; C’est la première chose qui m’est venue à l’esprit lorsque j’ai lu «grand nombre de [fichiers]» et «NTFS» (Windows).
Rob

lien vers le bas ........................
Pacerier

7

Quoi que vous fassiez, ne les stockez pas tous dans un seul répertoire.

En fonction de la distribution des noms de ces images, vous pouvez créer une structure de répertoire dans laquelle vous avez des dossiers de lettre unique de premier niveau, dans lesquels vous disposerez d'un autre ensemble de sous-dossiers pour la deuxième lettre d'images, etc.

Alors:

Le dossier img\a\b\c\d\e\f\g\contiendrait les images commençant par 'abcdefg' et ainsi de suite.

Vous pouvez introduire votre propre profondeur appropriée requise.

Le grand avantage de cette solution est que la structure de répertoires agit efficacement comme un hashtable / dictionary. Avec un nom de fichier image, vous connaîtrez son répertoire et un répertoire, vous connaîtrez un sous-ensemble d’images qui y vont.


\ a \ b \ c \ d \ e \ f \ i je le fais maintenant, je pensais qu'il y avait un moyen sage de le faire.
Samedi

1
C'est une solution généralement acceptée de la façon de les stocker physiquement. Générer clairement les URL de l'image est quelque chose qui peut être facilement fait de manière dynamique en fonction du nom du fichier image. En outre, pour les servir, vous pouvez même introduire des sous-domaines img-a, img-b sur le serveur d'images si vous le souhaitez, afin d'accélérer les temps de chargement.

2
Et +1 pour "ne les stockez pas tous dans un seul répertoire". Je prends en charge un système hérité qui a placé plus de 47 000 fichiers sur un serveur dans un seul dossier, et il faut environ une minute à Explorer pour ouvrir le dossier.
Mark Ransom

5
Faire un \ b \ c \ d \ e \ f \ g rend la structure de répertoires très profonde et chaque répertoire ne contient que quelques fichiers. Mieux vaut utiliser plus d’une lettre par niveau de répertoire, par exemple ab \ cd \ ef \ ou abc \ def \. Les répertoires prennent également de la place sur le disque, vous ne voulez donc pas en avoir trop.
Juha Syrjälä

2
Je devais prendre en charge une application contenant plus de 4 millions de fichiers dans un seul répertoire. cela a fonctionné étonnamment bien, mais vous ne pouviez JAMAIS que l'explorateur ouvre le dossier, il trierait continuellement les nouveaux ajouts. +1 pour NTFS capable de le gérer sans mourir.
SqlACID

5

Je voudrais les stocker sur le système de fichiers, mais cela dépend de la vitesse à laquelle le nombre de fichiers va augmenter. Ces fichiers sont-ils hébergés sur le Web? Combien d'utilisateurs accéderaient à ce fichier? Ce sont les questions auxquelles il faut répondre avant que je puisse vous donner une meilleure recommandation. Je voudrais aussi regarder Haystack de Facebook, ils ont une très bonne solution pour stocker et servir des images.

De plus, si vous choisissez le système de fichiers, vous devrez partitionner ces fichiers avec des répertoires. J'ai examiné cette question et proposé une solution, mais ce n'est pas une solution parfaite, loin de là. Je partitionne par table de hachage et les utilisateurs peuvent en lire plus sur mon blog .


les images ne sont pas destinées à un accès fréquent. donc il n'y a pas de problème avec cela. leur nombre augmentera assez vite. Je suppose qu'il y aura le 1mil. marquer dans 1 mois.
Samedi

je suis intéressé par le point de vue du programmeur afin que je ne pense pas trop à cela
s.mihai

Donc, si vous n'avez pas besoin d'un accès rapide, Haystack n'est probablement pas pour vous. Utiliser des répertoires pour les partitions est la solution la plus simple à mon sens.
Lukasz

5

Nous avons un système de magasin de photos avec 4 millions d'images. Nous utilisons la base de données uniquement pour les métadonnées et toutes les images sont stockées sur le système de fichiers à l'aide d'un système de dénomination inversée, où les noms de dossier sont générés à partir du dernier chiffre du fichier, last-1, etc. Par exemple: 000001234.jpg est stocké dans une structure de répertoires telle que 4 \ 3 \ 2 \ 1 \ 000001234.jpg.

Ce schéma fonctionne très bien avec l’index d’identité de la base de données, car il remplit uniformément la structure de répertoires.


4

Point rapide, vous n'avez pas besoin de stocker un chemin de fichier dans votre base de données. Vous pouvez simplement stocker une valeur numérique, si vos fichiers sont nommés de la manière que vous décrivez. Ensuite, en utilisant l’un des schémas de stockage bien définis déjà décrits, vous pouvez obtenir l’index sous forme de nombre et retrouver très rapidement le fichier en parcourant la structure de répertoires.


: -? bon point rapide. juste que maintenant je n'ai pas d'algorithme pour générer le chemin.
Samedi


4

Vos images devront-elles porter un nom unique? Le processus qui génère ces images peut-il générer plusieurs fois le même nom de fichier? Difficile à dire sans savoir quel périphérique crée le nom de fichier, mais il est «réinitialisé» et lors du redémarrage, il commence à nommer les images comme il l'avait fait la dernière fois qu'il a été réinitialisé - si cela pose un problème.

En outre, vous dites que vous atteindrez 1 million d'images dans un mois. Et après ça? À quelle vitesse ces images continueront-elles à remplir le système de fichiers? Vont-ils finir par atteindre un million d'images TOTAL ou continueront-ils à se développer mois après mois?

Je vous le demande parce que vous pouvez commencer à concevoir votre système de fichiers par mois, puis par image. Je pourrais être enclin à vous suggérer de stocker les images dans une telle structure de répertoires:

imgs\yyyy\mm\filename.ext

where: yyyy = 4 digit year
         mm = 2 digit month

example:  D:\imgs\2009\12\aaa0001.jpg
          D:\imgs\2009\12\aaa0002.jpg
          D:\imgs\2009\12\aaa0003.jpg
          D:\imgs\2009\12\aaa0004.jpg
                   |
          D:\imgs\2009\12\zzz9982.jpg
          D:\imgs\2010\01\aaa0001.jpg (this is why I ask about uniqueness)
          D:\imgs\2010\01\aab0001.jpg

Mois, année, même jour est bon pour les images de type sécurité. Je ne suis pas sûr que ce soit ce que vous faites, mais je l'ai fait avec une caméra de sécurité pour la maison qui prenait une photo toutes les 10 secondes ... Ainsi, votre application peut accéder à une heure précise ou même à une plage dans laquelle vous pourriez penser que l'image a été générée . Ou, au lieu d'année, de mois, existe-t-il un autre "sens" pouvant être dérivé du fichier image lui-même? Quelques autres descripteurs, autres que la date que j'ai donnée?

Je ne voudrais pas stocker les données binaires dans la base de données. Jamais eu de bonnes performances / chance avec ce genre de chose. Je ne peux pas imaginer que cela fonctionne bien avec 1 million d'images. Je voudrais stocker le nom de fichier et c'est tout. S'ils vont tous être au format JPG, ne stockez même pas l'extension. Je créerais une table de contrôle qui stockerait un pointeur sur le serveur, le lecteur, le chemin d'accès, etc. du fichier. Vous pourrez ainsi déplacer ces images dans une autre boîte tout en les localisant. Avez-vous besoin de taguer vos images par mots-clés? Si tel est le cas, vous souhaitez créer les tables appropriées qui permettent ce type de marquage.

Vous (ou d’autres) avez peut-être abordé ces idées pendant que je répondais. J'espère que cela vous aidera.


1.tous les fichiers seront nommés de manière unique. 2.Le système va grandir et grandira au début, il sortira environ 1 million d'images puis grossira au rythme de quelques dizaines de milliers par mois. 3.il y aura une sorte de marquage des fichiers à un moment donné dans le futur, c'est pourquoi je veux stocker une sorte de données d'identification dans la base de données.
Samedi

3

Je participe à un projet qui stocke 8,4 millions d'images au cours d'une année pour documenter le statut de divers périphériques. Les images plus récentes sont consultées plus fréquemment et les images plus anciennes sont rarement recherchées, à moins de découvrir une condition qui aurait incité quelqu'un à consulter les archives.

Ma solution, basée sur cet usage, consistait à compresser les images en fichiers compressés. Les images sont au format JPG, chacune d’environ 20 Ko et ne se compressent pas beaucoup, de sorte que le schéma de compression ZIP est nul. Ceci est fait simplement pour les concaténer dans une entrée de système de fichiers, ce qui aide grandement NTFS en termes de rapidité lorsqu'il s'agit de les déplacer d'un lecteur à l'autre ou de parcourir la liste des fichiers.

Les images plus anciennes qu'un jour sont combinées dans un zip "quotidien"; les zips âgés de plus d'un mois sont combinés dans leur zip "mensuel" respectif; et finalement tout ce qui dépasse l'année n'est plus nécessaire et par conséquent supprimé.

Ce système fonctionne bien car les utilisateurs peuvent parcourir les fichiers (via le système d’exploitation ou un certain nombre d’applications client) et tout est nommé en fonction des noms de périphérique et des horodatages. Généralement, un utilisateur connaît ces deux informations et peut rapidement localiser l’une des millions d’images.

Je comprends que cela n’est probablement pas lié à vos détails particuliers, mais j’ai pensé que je partagerais.


2

Peut-être un schéma de nommage basé sur la date de création: soit en incluant toutes les informations dans le nom du fichier, soit (mieux pour naviguer plus tard) en le divisant en répertoires. Je peux penser aux éléments suivants, en fonction de la fréquence à laquelle vous générez des images:

  • Plusieurs images générées chaque jour: Year/Month/Day/Hour_Minute_Second.png
  • Un couple par mois: Year/Month/Day_Hour_Minute_Second.png

etc. Vous obtenez mon point ... =)


ils ne sont pas générés en permanence au fil du temps, de sorte que certains dossiers vont grossir et que d'autres restent ... minces :))
s.mihai

Eh bien, vous n'avez évidemment pas besoin de créer chaque dossier, simplement parce que vous suivez ce schéma. Vous pourriez même avoir Year/Month/Day/Hour/Minute- décidez du nombre de niveaux de dossiers dont vous avez besoin en fonction de la fréquence à laquelle les images sont générées lorsque le taux est le plus élevé - et ne créez pas de dossiers qui seraient laissés vides.
Tomas Aschan

2

Je serais enclin à créer une structure de dossiers basée sur la date, par exemple, \ year \ month \ day, et à utiliser des horodatages pour les noms de fichiers. Si nécessaire, les horodatages peuvent avoir un composant compteur supplémentaire si les images doivent être créées si rapidement qu'il peut y en avoir plus d'une par milliseconde. En utilisant une séquence de plus en plus significative pour le tri des noms, la recherche et la maintenance deviennent un jeu d'enfant. par exemple hhmmssmm [seq] .jpg


2

Envisagez-vous une récupération après sinistre?

Certaines des solutions proposées ici finissent par modifier le nom du fichier (de telle sorte que si le fichier physique était déplacé, vous perdriez la trace du fichier en question). Je recommande de conserver un nom de fichier physique unique afin que, si votre liste principale d'emplacement de fichier soit corrompue, vous puissiez la régénérer avec un petit shell, euh, PowerShell, script;)

D'après ce que j'ai lu ici, il semble que tous ces fichiers seraient stockés sur un système de fichiers. Pensez à les stocker sur plusieurs systèmes de fichiers sur plusieurs ordinateurs. Si vous avez les ressources, déterminez un système permettant de stocker chaque fichier sur deux machines différentes au cas où vous perdriez une source d'alimentation et que le remplacement se fasse dans les 2 jours.

Déterminez les types de procédures à créer pour migrer des fichiers entre des ordinateurs ou des systèmes de fichiers. La possibilité de faire cela avec votre système est en direct et en ligne peut vous éviter des maux de tête considérables sur la route.

Vous pouvez envisager d'utiliser un GUID en tant que nom de fichier physique au lieu d'un numéro incrémentiel au cas où votre compteur de numéros incrémentiels (la colonne d'identité de la base de données?) Serait foiré.

Si nécessaire, envisagez d'utiliser un CDN tel qu'Amazon S3.


2

Bien que je n'aie pas servi d'images de cette envergure, j'ai déjà écrit une petite application de galerie pour servir environ 25 000 images sur une machine à 400 MHz w. 512 Mo de RAM ou plus. Quelques expériences;

  • Évitez les bases de données relationnelles à tout prix; Bien que les bases de données soient intelligentes pour la gestion des données, elles ne sont pas conçues pour un tel usage (nous avons des bases de données clé-valeur spécialisées et hiérarchiques pour ce système appelé système de fichiers ). Bien que je n’aie rien d’autre qu’un pressentiment, je parierais que le cache de la base de données disparaît par la fenêtre, si vous lui lancez de gros blobs. Alors que mon matériel disponible était petit, ne pas toucher à la base de données lors de la recherche d’image donnait une vitesse supérieure à des ordres de grandeur.

  • Recherchez le comportement du système de fichiers. sur ext3 (ou était-ce ext2 à l'époque - je ne m'en souviens pas), la limite de capacité à rechercher efficacement des sous-répertoires et des fichiers se situait autour de 256; il n’ya donc que beaucoup de fichiers et de dossiers dans un dossier donné. Encore une fois, accélération notable. Bien que je ne connaisse pas NTFS, des choses comme XFS (qui utilise des arbres B, si je me souviens bien) sont extrêmement rapides, tout simplement parce qu’elles peuvent effectuer des recherches extrêmement rapidement.

  • Distribuez les données de manière uniforme. Lorsque j'ai essayé ce qui précède, j'ai essayé de répartir les données uniformément sur tous les répertoires (j'ai créé un MD5 de l'URL et je l'ai utilisé pour les répertoires; /1a/2b/1a2b...f.jpg). De cette façon, il faut plus de temps pour atteindre la limite de performance (et le cache du système de fichiers est vide pour des ensembles de données aussi volumineux). (au contraire, vous voudrez peut-être voir où les limites sont précoces; ensuite, vous voulez tout jeter dans le premier répertoire disponible.


2

Pourrait être en retard au jeu à ce sujet. Mais une solution (si cela convient à votre cas d'utilisation) pourrait être le hachage du nom de fichier. C'est un moyen de créer un chemin de fichier facilement reproductible en utilisant le nom du fichier tout en créant une structure de répertoires bien distribuée. Par exemple, vous pouvez utiliser les octets du hashcode du nom de fichier comme chemin:

String fileName = "cat.gif";
int hash = fileName.hashCode();
int mask = 255;
int firstDir = hash & mask;
int secondDir = (hash >> 8) & mask;

Cela aurait pour résultat que le chemin soit:

/172/029/cat.gif

Vous pouvez ensuite trouver cat.gifdans la structure de répertoires en reproduisant l'algorithme.

Utiliser HEX comme noms de répertoire serait aussi simple que de convertir les intvaleurs:

String path = new StringBuilder(File.separator)
        .append(String.format("%02x", firstDir))
        .append(File.separator)
        .append(String.format("%02x", secondDir)
        .toString();

Résultant en:

/AC/1D/cat.gif

J'ai écrit un article à ce sujet il y a quelques années et je l'ai récemment déplacé vers Medium. Il contient quelques informations supplémentaires et un exemple de code: Hachage de noms de fichiers: création d'une structure de répertoire hachée . J'espère que cela t'aides!


Nous stockons 1,8 milliard d'articles en utilisant quelque chose de similaire. Ça marche bien. Utilisez un hachage rapide avec un faible taux de collisions et vous êtes prêt.
CVVS


1

Si TOUTES ne sont pas immédiatement nécessaires et que vous pouvez les générer à la volée et qu'il s'agisse de petites images, pourquoi ne pas implémenter une mémoire cache LRU ou un cache disque au-dessus de votre générateur d'images?

Cela pourrait vous sauver de la mémoire et garder les images chaudes à être servies de mem?


1

Je viens de faire un test sur zfs parce que j'adore zfs, et j'avais une partition de 500gig sur laquelle j'avais une compression. J'ai écrit un script qui générait 50 à 100 000 fichiers et les plaçais dans des répertoires imbriqués 1/2/3/4/5/6/7/8 (5 à 8 niveaux de profondeur) et le laissais fonctionner pendant une semaine, à mon avis. (Ce n'était pas un bon script.) Il remplit le disque et finit par avoir environ 25 millions de fichiers. L'accès à n'importe quel fichier avec un chemin connu était instantané. La liste de tous les répertoires avec un chemin connu était instantanée.

Obtenir un décompte de la liste des fichiers a cependant pris (via find) 68 heures.

J'ai également fait un test en mettant beaucoup de fichiers dans un seul répertoire. Je me suis levé à environ 3,7 millions de fichiers dans un répertoire avant de m'arrêter. Lister le répertoire pour obtenir un compte a pris environ 5 minutes. La suppression de tous les fichiers de ce répertoire a pris 20 heures. Mais la recherche et l'accès à n'importe quel fichier étaient instantanés.


1

Je vois que d’autres mentionnent une base de données, mais je ne vois aucune mention de cela dans votre message. Dans tous les cas, mon opinion sur ce point est la suivante: soit vous en tenez à une base de données ou à un système de fichiers. Si vous devez mélanger les deux, faites attention. Les choses se compliquent. Mais vous devrez peut-être. Stocker un million de photos dans une base de données ne semble pas la meilleure idée.

La spécification suivante pourrait vous intéresser. La plupart des appareils photo numériques la suivent pour gérer le stockage des fichiers: https://en.wikipedia.org/wiki/Camera_Image_File_Format

Essentiellement, un dossier est créé, tel que 000OLYMPUSet des photos sont ajoutées à ce dossier (par exemple DSC0000.RAW). Lorsque le compteur de noms de fichier atteint DSC9999.RAWun nouveau dossier est créé ( 001OLYMPUS) et une image est ajoutée à nouveau, en réinitialisant le compteur, éventuellement avec un préfixe différent (ex:) P_0000.RAW.

Alternativement, vous pouvez également créer des dossiers basés sur des parties du nom de fichier (déjà mentionné à plusieurs reprises). Par exemple, si votre photo est nommée IMG_A83743.JPG, stockez-la dans IMG_\A8\3\IMG_A83743.JPG. Il est plus compliqué à mettre en œuvre mais rendra vos fichiers plus faciles à trouver.

Selon le système de fichiers (cela nécessitera des recherches), vous pourrez peut-être vider toutes les images dans un seul dossier, mais, selon mon expérience, cela causerait généralement des problèmes de performances.


0

Vous voudrez peut-être regarder ZFS (système de fichiers, gestionnaire de volumes de Sun) Cordialement


0

Un moyen propre de générer le chemin à partir d'un grand nombre est de le convertir facilement en hex puis de le diviser!

par exemple 1099496034834> 0xFFFF1212>FF/FF/12/12

public string GeneratePath(long val)
{  
    string hex = val.ToString("X");
    hex=hex.PadLeft(10, '0');
    string path="";
    for(int i=0; i<hex.Length; i+=2 )
    {
        path += hex.Substring(i,2);
        if(i+2<hex.Length)
            path+="/";
    }
    return path;
}

Stocker et charger:

public long Store(Stream doc)
{
   var newId = getNewId();
   var fullpath = GeneratePath(newId)
   // store into fullpath 
   return newId;
}

public Stream Load(long id)
{
   var fullpath = GeneratePath(newId)
   var stream = ... 
   return stream;
}

Codes sources complets: https://github.com/acrobit/AcroFS


-1

Malheureusement, les systèmes de fichiers gèrent un grand nombre de petits fichiers (performances avec plusieurs fichiers par répertoire ou arborescences de répertoires profonds, vérification des temps de redémarrage, fiabilité). La solution ci-dessus impliquant des fichiers ZIP est donc préférable si vous souhaitez utiliser un système de fichiers.

L'utilisation d'un gestionnaire de base de données est de loin la meilleure option. un simple comme BDB ou GDBM par exemple; Même un SGBD relatif comme MySQL serait mieux. Seules les personnes paresseuses qui ne comprennent pas les systèmes de fichiers et les bases de données (par exemple, celles qui rejettent des transactions) ont tendance à utiliser les systèmes de fichiers comme bases de données (ou un peu plus rarement, vice-versa).


-2

Que diriez-vous d'une base de données avec une table contenant un ID et un BLOB pour stocker l'image? Vous pouvez ensuite ajouter de nouvelles tables chaque fois que vous souhaitez associer d'autres éléments de données à une photo.

Si vous vous attendez à évoluer, pourquoi ne pas évoluer maintenant? Vous gagnerez du temps à la fois maintenant et plus tard, IMO. Implémentez la couche base de données une fois, ce qui est assez facile pour commencer. Ou implémentez quelque chose avec des dossiers et des noms de fichiers et blah blah blah, puis passez à autre chose lorsque vous commencez à faire sauter MAX_PATH.


5
Été là, fait cela, avoir les cicatrices pour le prouver. Les bases de données qui stockent des images en grand nombre sont grincheuses presque inimaginables et nécessitent une maintenance démesurée. Mieux vaut les stocker dans le système de fichiers, sauf si vous avez un besoin spécifique auquel seule une base de données peut répondre (le nôtre était suivi de la version.)
Satanicpuppy

1
Et il existe de nombreux utilitaires pour gérer les fichiers et les systèmes de fichiers, mais il y en a peu pour gérer les fichiers dans une base de données.
Mark Ransom

2
Oh mon Dieu. S'il vous plaît, n'utilisez pas une base de données comme un grand stockage BLOB.
Neil N

Eek. Je ne savais pas que les bases de données (encore?) Ont tant de problèmes avec les BLOB.

Comment une si mauvaise solution qui a tant de commentaires peut-elle encore avoir un +1? sans vouloir offenser l’OP (je vois que ça vient de SO) mais le bouton de vote négatif est ici pour une raison!
Mark Henderson
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.