Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Atualização em massa Sqlalchemy no MySQL funciona muito devagar


Você pode acelerar as operações de atualização em massa com um truque, mesmo que o servidor de banco de dados (como no seu caso) tenha uma latência muito ruim. Em vez de atualizar sua tabela diretamente, você usa uma tabela de palco para inserir seus novos dados muito rapidamente, faça uma atualização de junção para a tabela de destino . Isso também tem a vantagem de reduzir drasticamente o número de instruções que você precisa enviar para o banco de dados.

Como isso funciona com ATUALIZAÇÕES?


Digamos que você tenha uma tabela entries e você tem novos dados chegando o tempo todo, mas você só quer atualizar aqueles que já foram armazenados. Você cria uma cópia de sua tabela de destino entries_stage com apenas os campos relevantes nele:
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),
)

Em seguida, você insere seus dados com uma inserção em massa. Isso pode ser acelerado ainda mais se você usar a sintaxe de inserção de valores múltiplos do MySQL, que não é suportada nativamente pelo SQLAlchemy, mas pode ser construída sem muita dificuldade.
INSERT INTO enries_stage (`id`, `value`)
VALUES
(1, 'string1'), (2, 'string2'), (3, 'string3'), ...;

No final, você atualiza os valores da tabela de destino com os valores da tabela de estágio assim:
 UPDATE entries e
 JOIN entries_stage es ON e.id = es.id
 SET e.value = es.value;

Então você está feito.

E as inserções?


Isso também funciona para acelerar as inserções, é claro. Como você já tem os dados na tabela de palco , tudo que você precisa fazer é emitir um INSERT INTO ... SELECT declaração, com os dados que não estão na tabela de destino ainda.
INSERT INTO entries (id, value)
SELECT FROM entries_stage es
LEFT JOIN entries e ON e.id = es.id
HAVING e.id IS NULL;

O bom disso é que você não precisa fazer INSERT IGNORE , REPLACE ou ON DUPLICATE KEY UPDATE , que incrementará sua chave primária, mesmo que não faça nada .