postgresql: ¿cómo obtener claves primarias de filas insertadas con un copy_from a granel?

bulk performance postgresql sql sqlbulkcopy

Pregunta

El objetivo es el siguiente: tengo un conjunto de valores para ir a la tabla A , y un conjunto de valores para ir a la tabla B Los valores que entran en B valores de referencia B en A (a través de una clave foránea), por lo que, después de insertar los valores A , necesito saber cómo hacer referencia a ellos cuando se insertan los valores B Necesito que esto sea lo más rápido posible.

Hice la inserción de valores B con una copia masiva 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))

Esto fue mucho más rápido que hacer una consulta de INSERT VALUES ... RETURNING id . Me gustaría hacer lo mismo para los valores A , pero necesito saber los id de las filas insertadas.

¿Hay alguna forma de ejecutar una copia masiva de esta manera, pero para obtener el campo de id (clave principal) de las filas que se insertan, de manera que sepa qué id asocia con qué value ?

Si no, ¿cuál sería la mejor manera de lograr mi objetivo?

EDITAR: Datos de muestra a petición:

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]

Quiero insertar los a_vals , luego insertar los b_vals , usando claves externas en lugar de referencias a los objetos de la lista.

Respuesta aceptada

Genera las identificaciones tú mismo.

  1. COMENZAR transacción
  2. Tabla de bloqueo a
  3. llama a nextval () - esa es tu primera identificación
  4. genere su COPIA con ID en su lugar
  5. lo mismo para la mesa b
  6. llame a setval () con su ID final + 1
  7. Transacción de COMPROMISO

En el paso 2, es probable que también desee bloquear la relación de la secuencia. Si el código llama a nextval () y guarda ese ID en algún lugar, es posible que ya esté en uso para el momento en que lo use.

Hecho ligeramente fuera de tema: hay una configuración de "caché" que puede establecer si tiene muchos backends haciendo muchas inserciones. Eso incrementa el contador en bloques.

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


Respuesta popular

En realidad puedes hacerlo de manera diferente, lo que necesitas es:

  • Iniciar transaccion
  • Crear tabla temporal con el mismo esquema (o casi el mismo)
  • COPY datos a esa tabla temporal
  • Ejecute regullar INSERT INTO .. FROM temp_table ... RETURNING id, other_columns
  • Cometer

tomado de aquí (en c #, pero algo es lo mismo)



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué