postgresql: comment obtenir les clés primaires des lignes insérées avec un copy_from en vrac?

bulk performance postgresql sql sqlbulkcopy

Question

L’objectif est le suivant: j’ai un ensemble de valeurs à intégrer dans le tableau A et un ensemble de valeurs à intégrer dans le tableau B Les valeurs entrant dans B référencent des valeurs dans A (via une clé étrangère), donc après avoir inséré les valeurs A , je dois savoir comment les référencer lors de l'insertion des valeurs B J'ai besoin que cela soit aussi rapide que possible.

J'ai fait l'insertion des valeurs B avec une copie en bloc à partir de:

def bulk_insert_copyfrom(cursor, table_name, field_names, values):
    if not values: return

    print "bulk copy from prepare..."
    str_vals = "\n".join("\t".join(adapt(val).getquoted() for val in cur_vals) for cur_vals in values)
    strf = StringIO(str_vals)
    print "bulk copy from execute..."
    cursor.copy_from(strf, table_name, columns=tuple(field_names))

C'était beaucoup plus rapide que de faire une requête INSERT VALUES ... RETURNING id . J'aimerais faire la même chose pour les valeurs A , mais j'ai besoin de connaître les id des lignes insérées.

Existe-t-il un moyen d’exécuter une copie en bloc de cette manière, mais en récupérant le champ id (clé primaire) des lignes insérées, de sorte que je sache quel id s’associe à quelle value ?

Sinon, quel serait le meilleur moyen d'atteindre mon objectif?

EDIT: Exemple de données sur demande:

a_val1 = [1, 2, 3]
a_val2 = [4, 5, 6]
a_vals = [a_val1, a_val2]

b_val1 = [a_val2, 5, 6, 7]
b_val2 = [a_val1, 100, 200, 300]
b_val3 = [a_val2, 9, 14, 6]
b_vals = [b_val1, b_val2, b_val3]

Je veux insérer les a_vals , puis les b_vals , en utilisant des clés étrangères au lieu de références aux objets de la liste.

Réponse acceptée

Générez vous-même les identifiants.

  1. BEGIN transaction
  2. Verrouiller la table a
  3. appelle nextval () - c'est ton premier identifiant
  4. générer votre copie avec les identifiants en place
  5. idem pour la table b
  6. appelez setval () avec votre identifiant final + 1
  7. Transaction COMMIT

A l'étape 2, vous souhaiterez probablement également verrouiller la relation de la séquence. Si le code appelle nextval () et bloque cet ID quelque part, il est peut-être déjà utilisé au moment où il l'utilise.

Fait légèrement différent du sujet: il existe un paramètre de "cache" que vous pouvez définir si vous avez beaucoup de moteurs de traitement faisant beaucoup d'insertions. Cela incrémente le compteur en blocs.

http://www.postgresql.org/docs/9.1/static/sql-createsequence.html


Réponse populaire

En fait, vous pouvez le faire différemment. Ce dont vous avez besoin est:

  • Commencer la transaction
  • Créer une table temporaire avec le même (ou presque) schéma
  • COPY données dans cette table temporaire
  • Effectue une recherche régulière INSERT INTO .. FROM temp_table ... RETURNING id, other_columns
  • Commettre

pris à partir d' ici (en c #, mais algo est le même)



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi