Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Sqlalchemy-Massenaktualisierung in MySQL funktioniert sehr langsam

Mit einem Trick können Sie Bulk-Update-Operationen beschleunigen, auch wenn der Datenbank-Server (wie in Ihrem Fall) eine sehr schlechte Latenz hat. Anstatt Ihre Tabelle direkt zu aktualisieren, verwenden Sie eine stage-table Um Ihre neuen Daten sehr schnell einzufügen, führen Sie dann ein Join-Update für die Zieltabelle durch . Dies hat auch den Vorteil, dass Sie die Anzahl der Anweisungen, die Sie an die Datenbank senden müssen, erheblich reduzieren.

Wie funktioniert das mit UPDATEs?

Angenommen, Sie haben eine Tabelle entries und Sie haben ständig neue Daten, möchten aber nur die bereits gespeicherten aktualisieren. Sie erstellen eine Kopie Ihrer Zieltabelle entries_stage mit nur den relevanten Feldern darin:

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),
)

Anschließend fügen Sie Ihre Daten per Bulk-Insert ein. Dies kann noch weiter beschleunigt werden, wenn Sie MySQLs Multiple-Value-Insert-Syntax verwenden, die von SQLAlchemy nicht nativ unterstützt wird, aber ohne große Schwierigkeiten erstellt werden kann.

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

Am Ende aktualisieren Sie die Werte der Zieltabelle mit den Werten aus der Etappentabelle wie folgt:

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

Dann sind Sie fertig.

Was ist mit Beilagen?

Dies funktioniert natürlich auch, um Einfügungen zu beschleunigen. Da Sie die Daten bereits in der stage-table haben , alles, was Sie tun müssen, ist ein INSERT INTO ... SELECT auszugeben Anweisung, mit den Daten, die nicht in der destination-table sind noch.

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

Das Schöne daran ist, dass Sie INSERT IGNORE nicht ausführen müssen , REPLACE oder ON DUPLICATE KEY UPDATE , die Ihren Primärschlüssel erhöhen, auch wenn sie nichts tun .