J'ai un ensemble de données dans un fichier CSV composé de 2500 lignes. Le fichier est structuré (simplifié) façon:Alternative à "écrire dans un fichier" pour transférer des données CSV à PostgreSQL en utilisant COPY pour de meilleures performances?
id_run; run_name; receptor1; receptor2; receptor3_value; [...]; receptor50_value
Chaque récepteur du fichier est déjà dans une table et un identifiant unique.
J'ai besoin de télécharger chaque ligne à une table avec ce format:
id_run; id_receptor; receptor_value
1; 1; 2.5
1; 2; 3.2
1; 3, 2.1
[...]
2500, 1, 2.4
2500, 2, 3.0
2500, 3, 1.1
En fait, j'écris toutes les données que je dois télécharger dans un fichier txt et j'utilise la commande COPY à partir de postgreSQL pour transférer le fichier dans la table de destination.
Pour 2500 exécutions (donc 2500 lignes dans le fichier CSV) et 50 récepteurs, mon programme Python génère ~ 110000 enregistrements dans le fichier texte à télécharger.
Je supprime les clés étrangères de la table de destination et les restaure après le téléchargement.
En utilisant cette méthode, il faut environ ~ 8 secondes pour générer le fichier texte et 1 seconde pour copier le fichier dans la table.
Existe-t-il un moyen, une méthode, une bibliothèque ou tout autre moyen que je pourrais utiliser pour accélérer la préparation des données afin que 90% du temps requis ne soit pas consacré à l'écriture du fichier texte?
Edit: Code
Voici mon (mis à jour). J'utilise maintenant une écriture en bloc dans le fichier texte. Il semble l'aimer plus vite (téléchargé 110 000 lignes en 3,8 secondes).
# Bulk write to file
lines = []
for line_i, line in enumerate(run_specs):
# the run_specs variable consists of the attributes defining a run
# (id_run, run_name, etc.). So basically a line in the CSV file without the
# receptors data
sc_uid = get_uid(db, table_name) # function to get the unique ID of the run
for rec_i, rec in enumerate(rec_uids):
# the rec_uids variable is the unique IDs in the database for the
# receptors in the CSV file
line_to_write = '%s %s %s\n' % (sc_uid, rec, rec_values[line_i][rec_i])
lines.append(line_to_write)
# write to file
fn = r"data\tmp_data_bulk.txt"
with open(fn, 'w') as tmp_data:
tmp_data.writelines(lines)
# get foreign keys of receptor_results
rr_fks = DB.get_fks(conn, 'receptor_results') # function to get foreign keys
# drop the foreign keys
for key in rr_fks:
DB.drop_fk(conn, 'receptor_results', key[0]) # funciton to drop FKs
# upload data with custom function using the COPY SQL command
DB.copy_from(conn, fn, 'receptor_results', ['sc_uid', 'rec_uid', 'value'],\
" ", False)
# restore foreign keys
for key in rr_fks:
DB.create_fk(conn, 'receptor_results', key[0], key[1], key[2])
# commit to database
conn.commit()
Edit # 2:
Utilisation de la bibliothèque cStringIO, j'ai remplacé la création d'un fichier texte temporaire avec un objet type fichier, mais les gains de vitesse est très très faible.
code modifié:
outf = cStringIO.StringIO()
for rec_i, rec in enumerate(rec_uids):
outf.write('%s %s %s\n' % (sc_uid, rec, rec_values[line_i][rec_i]))
cur.copy_from(outf, 'receptor_results')
Quel code utilisez-vous actuellement? [mcve] –
J'ai édité le post principal avec mon code! – kaycee
Si votre question est sur la façon de préparer vos données texte rapidement, alors il n'a rien à voir avec le serveur de base de données. Ceci est déroutant. –