update tutorial remove queries delete python flask sqlalchemy flask-sqlalchemy

python - tutorial - Inserciones a granel con Flask-SQLAlchemy



sqlalchemy documentation (2)

Estoy usando Flask-SQLAlchemy para hacer una inserción masiva bastante grande de 60k filas. También tengo una relación de muchos a muchos en esta tabla, por lo que no puedo usar db.engine.execute para esto. Antes de insertar, necesito encontrar elementos similares en la base de datos y cambiar la inserción a una actualización si se encuentra un elemento duplicado.

Podría hacer esta comprobación de antemano, y luego hacer una inserción masiva a través de db.engine.execute , pero necesito la clave primaria de la fila al insertarla.

Actualmente, estoy haciendo un db.session.add() y db.session.commit() en cada inserción, y obtengo un mísero 3-4 inserts por segundo.

Ejecuté un generador de perfiles para ver dónde está el cuello de botella, y parece que el db.session.commit() está tomando el 60% del tiempo.

¿Hay alguna forma que me permita hacer esta operación más rápido, tal vez agrupando commits, pero que me devolvería las claves primarias?

Así es como se ven mis modelos:

class Item(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(1024), nullable=True) created = db.Column(db.DateTime()) tags_relationship = db.relationship(''Tag'', secondary=tags, backref=db.backref(''items'', lazy=''dynamic'')) tags = association_proxy(''tags_relationship'', ''text'') class Tag(db.Model): id = db.Column(db.Integer, primary_key=True) text = db.Column(db.String(255))

Mi operación de inserción se ejecuta así:

for item in items: if duplicate: update_existing_item else: x = Item() x.title = "string" x.created = datetime.datetime.utcnow() for tag in tags: if not tag_already_exists: y = Tag() y.text = "tagtext" x.tags_relationship.append(y) db.session.add(y) db.session.commit() else: x.tags_relationship.append(existing_tag) db.session.add(x) db.session.commit()


Quizás debería intentar db.session.flush() para enviar los datos al servidor, lo que significa que se generarán las claves principales. Al final puede db.session.commit() para comprometer la transacción.


Utilizo el siguiente código para leer rápidamente el contenido de un panda DataFrame en SQLite. Tenga en cuenta que elude las características ORM de SQLAlchemy. myClass en este contexto es una clase derivada de db.Model que tiene un nombre de tabla asignado. Como los fragmentos de código mencionan, me adapté

l = df.to_dict(''records'') # bulk save the dictionaries, circumventing the slow ORM interface # c.f. https://gist.github.com/shrayasr/5df96d5bc287f3a2faa4 connection.engine.execute( myClass.__table__.insert(), l )