Algorithme de structure de répertoire de sharding

J'ai besoin de stocker un grand nombre, des millions, de fichiers sur le disque. Je veux utiliser une structure de répertoire sharding afin qu'il n'y ait pas plus de mille fichiers dans un répertoire. Si j'utilise 3 répertoires en profondeur, je peux obtenir un milliard de fichiers (1000 ^ 3).

Mes maths sont un peu rouillées et je ne suis pas sûr de la bonne formule pour savoir dans quel répertoire un fichier atterrirait étant donné une clé entière pour le fichier.

Par exemple, le fichier '0010.pdf' se retrouverait dans le répertoire '0000 \ 0000 \ 0000 \ 0010.pdf'. Le fichier '2010.pdf' entrerait dans '0000 \ 0000 \ 0002 \ 0010.pdf'. La structure est donc '{niveau 1} {niveau 2} {niveau 3} {fichier}'.

Comment puis-je calculer mathématiquement les différents niveaux? Je cherche une formule. Le code C# serait encore meilleur, mais je peux en déduire cela de la formule si besoin est.

Modifier

J'ai converti la réponse ci-dessous à une fonction c #.

public static string Shard(long key, string extension, int maxFiles = 1000, int depth = 3)
{
    var parts = new List();
    long current = key;

    for (int i = depth; i > 0; i--)
    {
        long q = Convert.ToInt64(Math.Pow(maxFiles, i));
        long level = current/q;

        parts.Add(string.Format("{0:0000}", level));

        current = current % q;
    }

    parts.Add(string.Format("{0:0000}{1}", current, extension));

    string separator = Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture);
    string path = string.Join(separator, parts);

    return path;
}
0
Avez-vous l'intention de stocker trop de fichiers sur le disque? Les performances NTFS vont considérablement diminuer. Sharding aidera seulement sur le formate de disque de ReFS.
ajouté l'auteur Akash Kava, source
technet.microsoft.com/fr-fr/library/cc781134.aspx, NTFS stocke tous les attributs de fichier dans une structure MFT quelle que soit la structure du répertoire. C'est la raison pour laquelle MS a investi dans ReFS qui a une MFT hiérarchique où chaque répertoire a sa propre table enfants. blogs.msdn.com/b/b8/archive/2012/01/16/… , cependa
ajouté l'auteur Akash Kava, source
Ma compréhension est que vous pouvez éviter les problèmes de performance en partageant dans des sous-dossiers. lien
ajouté l'auteur Paul Welter, source
Il y a plus de raisons de partitionner si votre système de fichiers le supporte. Vous pouvez en avoir besoin pour les limites du logiciel de sauvegarde, empêcher la surcharge des événements du système de fichiers, générer des prévisualisations de fichiers, mettre en miroir un système de fichiers plus limité, naviguer dans les fichiers Explorer ou Finder, partager le dossier via SMB, bibliothèques qui ont des problèmes d'itérer sur un très grand nombre de fichiers, le portage vers un autre système d'exploitation, etc. Je voudrais toujours partitionner une grande collection de fichiers à pas plu
ajouté l'auteur Eric, source

3 Réponses

Diviser par 1000 ^ 3 = 1000000000 (mod par 1000 - ne fait rien) pour obtenir le répertoire de premier niveau.

Diviser par 1000 ^ 2 = 1000000, mod par 1000, pour obtenir le répertoire de second niveau.

Divisez par 1000, mod par 1000, pour obtenir le répertoire de troisième niveau.

Mod par 1000 pour obtenir le fichier.

Remarquez comment cela peut simplement être fait avec une boucle forcée à partir de 1000 ^ 3, en divisant par 1000 à chaque étape.

Exemple:

Input: 123456789012

123456789012/1000000000     = 123
123456789012/1000000 % 1000 = 456
123456789012/1000 % 1000    = 789
123456789012 % 1000           = 012

Directory/file: 0123/0456/0789/0012

Ou, le faisant de manière itérative:
(en supprimant le % 1000 et en modifiant le nombre et la modification de l'étape précédente)

Input: 123456789012

123456789012/1000000000 = 123
123456789012 % 1000000000 = 456789012

456789012   /1000000    = 456
456789012    % 1000000    = 789012

789012      /1000       = 789
789012       % 1000       = 012

Prendre le résultat de chaque division, et le résultat final du mod:

Directory/file: 0123/0456/0789/0012

Note supplémentaire:

Vous pouvez probablement vous débarrasser de l'un des chiffres dans chaque niveau de votre structure - puisque vous n'avez que 0-999, il n'y a aucun intérêt à avoir 4 chiffres.

1
ajouté
Cela fonctionne très bien. Je vous remercie.
ajouté l'auteur Paul Welter, source

Puisque vous voulez une chaîne, traitez-la comme une chaîne:

private string MakePath(Int32 key)
{
   //make 9-digit string, pad left with 0
    string s = n.ToString().PadLeft(9, '0');

   //insert backslashes
    return s.Substring(0, 3) + "\\" + 
           s.Substring(3, 3) + "\\" + 
           s.Substring(6, 3);
}

Il y a des façons plus élégantes de coder ceci, bien sûr.

0
ajouté

Vous décrivez un hachage profond à 3 niveaux. La façon la plus évidente d'implémenter ceci est de construire 3 algorithmes de hachage différents dont chacun prend une chaîne et renvoie un nombre unique de 0 à 999 à chaque niveau.

En fonction de la taille et de la répartition homogène des valeurs entières pour chaque fichier, vous pouvez simplement utiliser un hachage trivial si les valeurs entières de chaque fichier sont uniques et inférieures à un milliard.

http://en.wikipedia.org/wiki/Hash_function

Si vous demandez comment obtenir 0123 à partir de 0123 993 456 simplement faire un nombre entier de 1 000 000.

Vous obtenez 993 en prenant le mod 1,0000,000 et diviser ensuite entier par 1000, etc.

pry
[1] pry(main)> foo = 123993456
 => 123993456
[2] pry(main)> foo/1000000
 => 123
[3] pry(main)> foo % 1000000
 => 993456
[4] pry(main)> foo % 1000000/1000
 => 993
[5] pry(main)> foo % 1000
=> 456
0
ajouté