2010-07-06 4 views
0

Je suis nouveau sur Python et Sqlite, donc je suis sûr qu'il y a une meilleure façon de le faire. J'ai un DB avec 6000 lignes, où 1 colonne est une chaîne XML 14K. Je voulais compresser toutes ces chaînes XML pour réduire la taille de la base de données. Malheureusement, le script ci-dessous est beaucoup, beaucoup plus lent que cette simple ligne de commande (qui prend quelques secondes).Compresser la colonne XML dans Sqlite avec Python est SLOW!

sqlite3 weather.db .dump | gzip -c > backup.gz 

Je sais que ce n'est pas la même chose, mais il ne sait ni lire/convertir le DB en texte et exécuter gzip. J'espérais donc que ce script serait dans les 10X performances, mais c'est plus comme 1000X plus lent. Y a-t-il un moyen de rendre le script suivant plus efficace? Merci.

import zlib, sqlite3 

conn = sqlite3.connect(r"weather.db") 
r = conn.cursor() 
w = conn.cursor() 
rows = r.execute("select date,location,xml_data from forecasts") 
for row in rows: 
    data = zlib.compress(row[2]) 
    w.execute("update forecasts set xml_data=? where date=? and location=?", (data, row[0], row[1])) 

conn.commit() 
conn.close() 
+1

J'ai l'impression que votre problème est avec votre schéma db et non le code Python. Exécutez 'explain select date, location, xml_data à partir de forecast', puis recherchez ce que signifie la sortie de explain http://dev.mysql.com/doc/refman/5.1/en/using-explain.html. En outre, exécutez l'une des mises à jour manuellement et voyez combien de temps il faut pour l'exécuter. – sberry

+0

J'utilise Sqlite, pas MySQL. – projectshave

Répondre

1

Désolé, mais commencez-vous implicitement une transaction dans votre code? Si vous effectuez une mise à jour automatique après chaque MISE À JOUR, cela vous ralentira considérablement.

Avez-vous un index approprié sur la date et/ou l'emplacement? Quel genre de variation avez-vous dans ces colonnes? Pouvez-vous utiliser une clé primaire entière numérotée dans cette table?

Enfin, pouvez-vous indiquer combien de temps vous passez dans les appels zlib et combien dans les UPDATEs? En plus des écritures de base de données qui vont ralentir ce processus, votre version de base de données implique 6000 appels (avec 6000 initialisations) de l'algorithme zip.

+0

Merci pour l'info.RE: Tx, je mets un commit après les mises à jour 6K, mais peut-être qu'il fait un autocommit après chaque UPDATE. Je vais vérifier ça. RE: index, je n'ai pas d'ensemble (je devrais en ajouter un). RE: zlib, je ne vois pas un moyen de réutiliser l'objet de compression zlib. Je vais vérifier ça. – projectshave

2

Vous ne pouvez pas améliorer les performances en effectuant une mise à jour après coup. il y a trop de frais généraux entre faire la compression et mettre à jour le dossier. vous ne gagnerez pas d'économies d'espace à moins de faire un vide après avoir terminé les mises à jour. la meilleure solution serait probablement de faire la compression lorsque les disques sont insérés pour la première fois. alors vous obtenez les économies d'espace et le coup de performance ne sera probablement pas aussi perceptible. Si vous ne pouvez pas le faire sur l'insert, alors je pense que vous avez exploré les deux possibilités et vu les résultats.

+0

Je pose cette question pour apprendre à écrire de meilleurs scripts de conversion DB chaque fois que je change le schéma. La perf était terrible avec seulement 6K lignes, que ferai-je quand j'ai besoin de mettre à jour 60K lignes dans un nouveau schéma? J'ai déjà lancé VACUUM et mis à jour mon script pour compresser sur INSERT. Il réduit l'espace de 10X. – projectshave

+0

comme mentionné ci-dessus (par Larry), envelopper les mises à jour à l'intérieur d'une transaction va certainement aider. vous devez expérimenter avec ça. peut-être faire une transaction de début, ajouter 10000 enregistrements, puis faire un commit. répétez tous les enregistrements 10k. comparez cela contre le faire pour chaque 1000 enregistrements, etc. jusqu'à ce que vous trouviez la meilleure performance. –

2

Vous comparez des pommes à des oranges ici. La grande différence entre la version sqlite3 | gzip et python est que le dernier écrit les modifications dans la base de données!

Qu'est-ce que sqlite3 | gzip fait est:

  • lire la db
  • gzip le texte

en plus de ce qui précède la version python écrit le texte gzip de nouveau dans la db avec un UPDATE par enregistrement lu.