Excluir em massa para tabela grande no MySQL

9

Eu tenho uma tabela de notificação que contém cerca de 100 milhões de linhas hospedadas no Amazon RDS com 1000 IOPS e desejo excluir essas linhas com mais de um mês.

Se o fizer DELETE FROM NOTIFICATION WHERE CreatedAt < DATE_SUB(CURDATE(), INTERVAL 30 day);, todas as IOPS serão realizadas, o processo levará horas e muitas entradas novas não poderão ser inseridas devido a "Tempo limite de espera de bloqueio excedido; tente reiniciar a transação".

Eu estava tentando fazer a maneira descrita aqui: http://mysql.rjweb.org/doc.php/deletebig No entanto, estou usando UUID em vez de ID de incremento.

Qual é a maneira correta e eficiente de excluir essas linhas sem afetar a inserção / atualização de novos dados?

Tianyi Cong
fonte
Você está correto ypercube, eu retifiquei. Obrigado por apontar!
Tianyi Cong
A exclusão de registros em partes menores, não afeta a operação de inserção, tentei com loop e conclui a exclusão de 70 milhões de registros em menos de uma hora rathishkumar.in/2017/12/…
Rathish

Respostas:

11

Crie uma tabela temporária, ligue e desligue e copie os dados dos últimos 30 dias nela.

#
# Make empty temp table
#
CREATE TABLE NOTIFICATION_NEW LIKE NOTIFICATION;
#
# Switch in new empty temp table
#
RENAME TABLE NOTIFICATION TO NOTIFICATION_OLD,NOTIFICATION_NEW TO NOTIFICATION;
#
# Retrieve last 30 days data 
#
INSERT INTO NOTIFICATION SELECT * FROM NOTIFICATION_OLD
WHERE CreatedAt >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);

Nas horas de folga, largue a mesa antiga

DROP TABLE NOTIFICATION_OLD;

Aqui estão as vantagens de fazer DELETEs como este

  1. NOTIFICATION é esvaziado rapidamente, alternando uma tabela vazia.
  2. NOTIFICATION está disponível imediatamente para novos INSERTs
  3. Os 30 dias restantes são adicionados novamente NOTIFICATIONenquanto novos INSERTs podem ocorrer.
  4. A eliminação da versão antiga do NOTIFICATIONnão interfere com os novos INSERTs
  5. NOTA: Eu recomendei fazer iscas e alternar para DELETEs de tabela antes: (Veja minha postagem de 19 de julho de 2012: Otimizando a consulta DELETE na tabela de memória do MySQL )

De uma chance !!!

RolandoMySQLDBA
fonte
Obrigado a resposta Rolando! Como o MySql lida internamente com drop table? Primeiro exclua todas as colunas e remova a tabela ou algo mais? Levará muito mais tempo do que excluir esses cloumns?
precisa
Estou aplicando essa estratégia no preparo. O comando renomear deve começar com "RENAME TABLE"?
Tianyi Cong
haveria alguma diferença se eu o usasse dentro de um bloco de transação, tendo em mente o tempo limite de espera de bloqueio, também teria algum contras se minha tabela real fosse realmente grande, que agora é renomeada e precisa ser descartada
Muhammad Omer Aslam
11
@MuhammadOmerAslam nesse caso, o arquivo ibdata1 (espaço de tabela do sistema) aumentaria apenas nos logs de desfazer. Esse é especialmente o caso em que o ibdata1 começaria a aumentar em tamanho de arquivo (veja meu post antigo dba.stackexchange.com/questions/40730/… ). Você precisa ter mais cuidado usando o pt-archiver, como mencionado na resposta de akuzminsky. Pode ser regulado para excluir linhas em pedaços e, em seguida, use pt-online-schema-change para executar ALTER TABLE ENGINE=InnoDB para reduzir a tabela.
RolandoMySQLDBA
11
@MuhammadOmerAslam A abordagem acima seria perfeita quando você agendasse o tempo de inatividade. Seguindo o link na resposta de akuzminsky ( percona.com/doc/percona-toolkit/LATEST/pt-archiver.html ). Você pode usar o pt-archiver para arquivar dados ou apenas excluir dados sem arquivar.
RolandoMySQLDBA
3

O meu favorito é o pt-archiver do Percona Toolkit. Ele cuida da carga do MySQL, atraso na replicação.

akuzminsky
fonte
Obrigado a resposta akuzminsky! Vou dar uma olhada. Eu costumava experimentar o Percona quando queria alterar essa tabela de notificação com pt-online-schema-change. No entanto, foi necessário o privilégio SUPER para fazer a alteração, que não é fornecida pelo RDS. BTW você conhece alguma maneira de alterar uma mesa enorme?
Tianyi Cong
@TianyiCong, você tem uma nova pergunta: faça-a como uma nova pergunta e, talvez, comente aqui com um link, não faça comentários nos comentários que não são como este site funciona.
Jack diz que tente topanswers.xyz
-2

crie a tabela notification_temp como selecione * da notificação em que CreatedAt <DATE_SUB (CURDATE (), INTERVAL 30 dias);

notificação de descartar tabela;

RENAME notification_temp TO NOTIFICATION;

user52557
fonte
E isso não afetará a inserção / atualização de novos dados? Acho que não.
Colin 't Hart
Este método possui 2 problemas 1) torna a NOTIFICAÇÃO indisponível durante a DROP TABLE. 2) INSERTs que ocorrem durante o CREATE TABLEsão perdidos.
RolandoMySQLDBA
Outro problema: deve-se dizerRENAME TABLE notification_temp ...
RolandoMySQLDBA