-
Fseek et offset
Bonjour à tous,
J'ai un fichier assez énorme (43Go) contenant des mots, un par ligne. Ce fichier est destiné à grandir.
Il me faut maintenant pouvoir effectuer des recherches dans ce fichier le plus vite possible, pour cela j'avais d'abord pensé à indexer les mots selon la ligne, mais je ne trouve rien pour faire une recherche instantanée en spécifiant une ligne (sed prend un certain temps, la recherche doit se faire en quelques ms).
Donc j'ai ensuite pensé à fseek, qui lui est instantané, mais a besoin de l'offset. J'ai donc crée un script perl pour créer un fichier contenant les références de chaque mot avec leur offset, mais l'offset prend vite beaucoup de place, et il me faut en plus stocker le nombre d'octets du mot pour le retourner (sauf si vous pensez à une autre solution, genre je fais un fseek à partir d'un offset jusqu'au prochain retour à la ligne ?).
Mon problème est donc de stocker l'offset sur le minimum de place possible, là il atteint les 10 à 11 caractères, ce qui fait beaucoup. Mon fichier wordlist contient des mots dont la moyenne est de 10 caractères, donc il me faudrait stocker l'offset sur 9 ou moins pour gagner de l'espace.
Auriez-vous une idée concernant le meilleur moyen d'indexer des mots dans le but de les lire avec fseek ?
Merci, et désolé si ça n'est pas très clair :)
EDIT : J'ai aussi essayé d'utiliser fwrite pour stocker le tout sous forme binaire, mais au final ça prenait plus de place. A moins que ne l'utilise mal ? Je fais un fopen en append puis j'écris avec fwrite avant de fclose.
-
Salut,
un fichier texte de 43 Go ?!!???
As-tu envisagé sérieusement de migrer le bouzin dans une base de données, je dis ça parce que cela devrait te simplifier vachement la vie.
-
43 Go ? Ca doit être bien plus que tous les mots dans toutes les langues.
-
Bonjour, et merci pour vos réponses.
Effectivement c'est bien plus que tous les mots de toutes les langues, c'est un fichier de passwords.
Le problème avec une base de données "normale" c'est la taille sur le disque qui devient absolument énorme. Hors je n'ai pas beaucoup de place et j'attend que mon hébergement normale prenne fin pour passer sur un dédié. Du coup en attendant j'essaie d'optimiser le tout (et d'ailleurs je trouve ça bien plus marrant).
Du coup pour le moment j'utilise des fichiers texte comme une database flat. En fait mon site contient une base de données permettant le reverse hashing de mots de passe. Mes "hashs" sont stockés sous la forme suivante :
Un dossier contenant 16 sous-dossier (de '0' à 'F'). Chacun de ces sous dossier contient des fichiers txt.gz nommés de 000 à FFF. Puis à l'intérieur de ces fichiers j'ai des lignes contenant [3 premiers caractères du hash][mot en clair]. Ce qui me permet de stocker un mot sur 14 bytes pour le moment.
Maintenant je cherche un moyen plus efficace de stocker le tout, pour pouvoir augmenter la base sans encore passer sur un dédié.
J'avais donc discuté avec un autre webmaster de site comme le mien, qui lui avait fait un index contenant [6 premiers caractères du hash][6 caractères de l'offset], et ce pour 15 milliards de mots (je n'en ai "que" 3.7). Je ne vois vraiment pas comment il fait pour stocker son offset sur 6 caractères, à moins de bruteforcer le reste, mais ça prendrait trop de temps.
Voilà pourquoi je cherche un moyen optimal en php (ou perl mais ça se transpose plutôt bien) pour écrire ces fichiers sous cette forme ou une autre, sans que ça prenne trop de place.
Concernant l'écriture de fichiers binaires, je me disais que ça serait plus optimal puisqu'on peut stocker un nombre hexadécimal sur 4 bits. Toutefois étant donné que je compresse mes fichiers pour utiliser ensuite zgrep, est-ce vraiment utile ou bien la compression effectue déjà cette optimisation pour moi ? De plus je n'ai pas réussi à écrire en mode binaire avec fwrite.
Merci à tous pour vos réponses, je ne travaille pas dans l'informatique à la base donc désolé pour mon manque de compétence.
EDIT : Concernant le débat entre sql / flat pour les bases, j'étais d'abord en sql mais le temps de réponse ainsi que le stockage étaient vraiment trop importants. Tous ceux que j'ai croisé avec plusde 10M de mots utilisent plutôt leur propre système. Pour faire une recherche sur un mot, il me faut entre 25 et 50ms, je vais jusqu'à 500 mots en ~40s.
Celà dit si vous avez une autre idée pour stocker autant de données sur peu de place et avec un temps de réponse acceptable je suis preneur, puisque je compte prendre un dédié.