sql >> Base de Datos >  >> RDS >> Mysql

La actualización masiva de Sqlalchemy en MySQL funciona muy lentamente

Puede acelerar las operaciones de actualización masiva con un truco, incluso si el servidor de la base de datos (como en su caso) tiene una latencia muy mala. En lugar de actualizar su tabla directamente, usa una tabla de escenario para insertar sus nuevos datos muy rápido, luego haga una actualización de unión a la tabla de destino . Esto también tiene la ventaja de que reduce drásticamente el número de extractos que tiene que enviar a la base de datos.

¿Cómo funciona esto con las ACTUALIZACIONES?

Digamos que tienes una tabla entries y recibe nuevos datos todo el tiempo, pero solo desea actualizar los que ya se han almacenado. Creas una copia de tu tabla de destino entries_stage con solo los campos relevantes:

entries = Table('entries', metadata,
    Column('id', Integer, autoincrement=True, primary_key=True),
    Column('value', Unicode(64), nullable=False),
)

entries_stage = Table('entries_stage', metadata,
    Column('id', Integer, autoincrement=False, unique=True),
    Column('value', Unicode(64), nullable=False),
)

Luego inserta sus datos con una inserción masiva. Esto se puede acelerar aún más si utiliza la sintaxis de inserción de valores múltiples de MySQL, que no es compatible de forma nativa con SQLAlchemy, pero se puede construir sin mucha dificultad.

INSERT INTO enries_stage (`id`, `value`)
VALUES
(1, 'string1'), (2, 'string2'), (3, 'string3'), ...;

Al final, actualiza los valores de la tabla de destino con los valores de la tabla de etapa de esta manera:

 UPDATE entries e
 JOIN entries_stage es ON e.id = es.id
 SET e.value = es.value;

Entonces ya está.

¿Qué pasa con las inserciones?

Esto también funciona para acelerar las inserciones, por supuesto. Como ya tienes los datos en la stage-table , todo lo que necesita hacer es emitir un INSERT INTO ... SELECT declaración, con los datos que no están en destination-table todavía.

INSERT INTO entries (id, value)
SELECT FROM entries_stage es
LEFT JOIN entries e ON e.id = es.id
HAVING e.id IS NULL;

Lo bueno de esto es que no tienes que hacer INSERT IGNORE , REPLACE o ON DUPLICATE KEY UPDATE , que aumentarán su clave principal, aunque no hagan nada .