Chargement d'un gros dictionnaire à l'aide de python cornichon
J'ai plein d'index inversé, en forme de imbriquée python dictionnaire. Sa structure est :
{word : { doc_name : [location_list] } }
Par exemple laisser le dictionnaire être appelé index, puis du mot " spam ", entrée ressemblerait à :
{ spam : { doc1.txt : [102,300,399], doc5.txt : [200,587] } }
J'ai utilisé cette structure comme python dict sont assez optimisé, et il rend la programmation plus facile.
pour n'importe quel mot "spam", les documents contenant qui peut être donnée par :
index['spam'].keys()
et l'affichage d'une liste pour un document doc1 par:
index['spam']['doc1']
À l'heure actuelle, je suis en utilisant cPickle de stocker et de charger ce dictionnaire. Mais le marinés fichier est d'environ 380 MO et prend beaucoup de temps à charger - 112 secondes(approx. Je l'ai chronométré à l'aide de temps.time()) et l'utilisation de la mémoire va à 1,2 GO (moniteur système de Gnome). Une fois son chargement, de sa belle. J'ai 4 go de RAM.
len(index.keys())
donne 229758
Code
import cPickle as pickle
f = open('full_index','rb')
print 'Loading index... please wait...'
index = pickle.load(f) # This takes ages
print 'Index loaded. You may now proceed to search'
Comment puis-je rendre le chargement plus rapide? J'ai seulement besoin de la charger une fois, lorsque l'application démarre. Après cela, le temps d'accès est important pour répondre à des requêtes.
Devrais-je passer à une base de données comme SQLite et de créer un index sur ses touches? Si oui, comment dois-je stocker les valeurs de disposer d'un schéma équivalent, ce qui rend la récupération facile. Est-il autre chose que je devrais regarder ?
Additif
À l'aide de Tim réponse pickle.dump(index, file, -1)
la marinés fichier est considérablement plus petites autour de 237 MO (a pris 300 secondes pour vider)... et prend la moitié du temps à charger maintenant (61 secondes ... plutôt 112 s plus tôt .... temps.time())
Mais dois-je migrer vers une base de données pour l'évolutivité ?
Que pour l'instant je suis marquage de Tim réponse acceptée.
PS :je ne veux pas utiliser Lucene ou Xapian ...
Cette question fait référence Le stockage d'un index inversé . Je devais poser une nouvelle question, parce que je n'étais pas en mesure de supprimer le précédent.
"Mais dois-je migrer vers une base de données pour l'évolutivité ?" Vous seul pouvez décider si le temps de chargement est un problème ou pas. Combien de fois avez-vous en charge? Le nombre de requêtes faites-vous fonctionner en comparaison avec le temps nécessaire pour charger? Cette ingénierie question qui exige des faits.
S. Lott : je voudrais essayer de la base de données de mise en œuvre. Il serait pour une bonne comparaison. J'ai encore beaucoup de temps pour le compléter. Le problème que j'ai maintenant est le stockage de l'index dans la base de données. Je pensais que le dictionnaire de la mise en œuvre était une bonne idée, mais qui ne sera pas possible dans une base de données. J'ai lu ces posts concernant le stockage de base de données stackoverflow.com/questions/1571140/... , stackoverflow.com/questions/3581792/... mais ils n'ont pas été d'une grande aide.
"dictionnaire de la mise en œuvre était une bonne idée, mais qui ne sera pas possible dans une base de données". Faux. Obtenir une meilleure ORM.
OriginalL'auteur easysid | 2010-10-18
Vous devez vous connecter pour publier un commentaire.
Essayer le protocole argument lors de l'utilisation de
cPickle.dump
/cPickle.dumps
. DecPickle.Pickler.__doc__
:De la conversion au format JSON ou YAML sera probablement plus long que le décapage, la plupart du temps - cornichon magasins natif Python les types.
C'est l'une compatibilité étape au-dessous de la valeur par défaut de Python 3.
OriginalL'auteur Tim McNamara
Avez-vous vraiment besoin de charger tout à la fois? Si vous n'avez pas besoin de tout ça dans la mémoire, mais seulement l'sélectionner les parties que vous voulez à un moment donné, vous souhaitez mapper votre dictionnaire à un ensemble de fichiers sur le disque au lieu d'un seul fichier... ou de la carte le dict à une table de base de données. Donc, si vous cherchez quelque chose qui sauve des grands dictionnaires de données sur disque ou à une base de données, et d'utiliser le décapage et l'encodage (codecs et hashmaps), alors vous voudrez peut-être regarder à
klepto
.klepto
fournit un dictionnaire d'abstraction pour l'écriture d'une base de données, y compris le traitement de votre système de fichiers comme une base de données (c'est à dire de l'écriture de la totalité du dictionnaire dans un fichier unique, ou de l'écriture de chaque entrée à son propre fichier). Pour les données de grande taille, j'ai souvent choisir de représenter le dictionnaire comme un répertoire sur mon système, et ont, à chaque entrée d'un fichier.klepto
propose également des algorithmes de mise en cache, donc, si vous utilisez un système de fichiers backend pour le dictionnaire, vous pouvez éviter certains pénalité sur la vitesse en utilisant la mémoire cache.klepto
a également d'autres indicateurs tels quecompression
etmemmode
qui peuvent être utilisés pour personnaliser la façon dont vos données sont stockées (par exemple, niveau de compression, la mémoire de la carte mode, etc).Il est tout aussi facile (exactement la même interface) pour utiliser un (MySQL, etc) base de données comme un backend à la place de votre système de fichiers. Vous pouvez également désactiver la mise en mémoire cache, de sorte que chaque lecture/écriture va directement à l'archive, en définissant simplement les
cached=False
.klepto
permet d'accéder à la personnalisation de votre encodage, par la construction d'une coutumekeymap
.klepto
fournit aussi beaucoup d'algorithmes de mise en cache (commemru
,lru
,lfu
, etc), pour vous aider à gérer votre cache en mémoire, et d'utiliser l'algorithme ne la décharge et de charge à l'archive principale pour vous.Vous pouvez utiliser le drapeau
cached=False
pour désactiver la mise en mémoire cache entièrement, et directement lire et à écrire et à partir du disque ou de la base de données. Si vos entrées sont assez grands, vous pouvez choisir d'écrire sur le disque, où vous placez chaque entrée dans son propre fichier. Voici un exemple qui fait les deux.Cependant, alors que cela devrait réduire considérablement les temps de chargement, il peut ralentir l'exécution globale vers le bas un peu... il est en général préférable de spécifier la quantité maximale de tenir dans la mémoire cache et chercher un bon algorithme de mise en cache. Vous avez à jouer avec elle pour obtenir le bon équilibre pour vos besoins.
Obtenir
klepto
ici: https://github.com/uqfoundationOriginalL'auteur Mike McKerns
Un modèle commun en Python 2.x est d'avoir une version d'un module mis en œuvre en pur Python, avec une option accélérée version implémenté comme une extension de do; par exemple,
pickle
etcPickle
. Ce met à la charge de l'importation de l'accélération de la version et de retomber sur la pure version de Python sur chacun de ces modules. En Python 3.0, par l'accélération des versions sont considérées comme des détails de mise en œuvre de la pure pour les versions de Python. Les utilisateurs devraient toujours importer la version standard, qui tente d'importer la version accélérée et revient à la pure version de Python. Le cornichon /cPickle paire reçu ce traitement.Si votre dictionnaire est énorme et ne doit être compatible avec Python 3.4 ou plus, utilisez:
ou:
Cela dit, en 2010 la
json
module a été 25 fois plus rapide, à l'encodage et à 15 fois plus rapide, à décoder les types simples quepickle
. Mon 2014 test ditmarshal
>pickle
>json
, maisdu maréchal
couplé à certains versions de Python.OriginalL'auteur Cees Timmerman
Avez-vous essayé d'utiliser une alternative format de stockage tels que YAML ou JSON? Python supporte JSON natif à partir de la version 2.6 de Python à l'aide de la
json
module je pense, et il y a modules tiers pour YAML.Vous pouvez également essayer les
shelve
module.OriginalL'auteur Tamás
Dependend sur combien de temps est "long" que vous avez à penser le compromis que vous avez à faire: soit toutes les données sont prêtes dans la mémoire après un (long) de démarrage, ou de ne charger que des données partielles (ensuite, vous devez diviser la date dans plusieurs fichiers ou l'utilisation de SQLite ou quelque chose comme ça). Je doute que le chargement de toutes les données d'avance, par exemple, d'sqlite dans un dictionnaire apportera aucune amélioration.
OriginalL'auteur knitti