A historia de eliminar fisicamente 300 millóns de rexistros en MySQL

Introdución

Ola. Son ningenMe, desenvolvedor web.

Como di o título, a miña historia é a historia da eliminación física de 300 millóns de rexistros en MySQL.

Intereseime nisto, así que decidín facer un recordatorio (instrucións).

Inicio - Alerta

O servidor por lotes que uso e manteño ten un proceso regular que recolle os datos do último mes de MySQL unha vez ao día.

Normalmente este proceso complétase en aproximadamente 1 hora, pero esta vez non se completou durante 7 ou 8 horas e a alerta non deixou de aparecer...

Buscando un motivo

Tentei reiniciar o proceso e mirar os rexistros, pero non vin nada mal.
A consulta indexouse correctamente. Pero cando pensei no que estaba a pasar mal, decateime de que o tamaño da base de datos é bastante grande.

hoge_table | 350'000'000 |

350 millóns de rexistros. A indexación parecía funcionar correctamente, pero moi lenta.

A recollida de datos requirida ao mes foi de aproximadamente 12 rexistros. Parece que o comando select levou moito tempo e a transacción non se executou durante moito tempo.

DB

É esencialmente unha táboa que crece nunhas 400 entradas cada día. A base de datos debía recoller datos só para o último mes, polo que se esperaba que soportara exactamente esta cantidade de datos, pero, por desgraza, non se incluíu a operación de rotación.

Esta base de datos non foi desenvolvida por min. Tomeino a outro programador, polo que aínda parecía unha débeda técnica.

Chegou un momento no que o volume de datos inseridos diariamente fíxose grande e finalmente chegou ao seu límite. Suponse que cando se traballa cunha cantidade tan grande de datos, sería necesario separalos, pero isto, por desgraza, non se fixo.

E entón entrei en acción.

Corrección

Era máis racional reducir o tamaño da propia base de datos e reducir o tempo para procesala que cambiar a propia lóxica.

A situación debería cambiar significativamente se borras 300 millóns de rexistros, así que decidín facelo... Eh, pensei que iso definitivamente funcionaría.

Acción 1

Despois de preparar unha copia de seguridade fiable, finalmente comecei a enviar solicitudes.

「Enviando unha solicitude」

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

"…"

"…"

"Hmm... Sen resposta. Quizais o proceso leva moito tempo?" — Pensei, pero por se acaso, mirei a grafana e vin que a carga do disco medraba moi rápido.
"Perigoso", pensei de novo e inmediatamente parei a solicitude.

Acción 2

Despois de analizalo todo, decateime de que o volume de datos era demasiado grande para borrar todo á vez.

Decidín escribir un guión que puidese borrar uns 1 de rexistros e púxeno a andar.

「Implemento o script」

"Agora isto definitivamente funcionará", pensei.

Acción 3

O segundo método funcionou, pero resultou ser moi laborioso.
Facelo todo con coidado, sen nervios innecesarios, levaría unhas dúas semanas. Pero aínda así, este escenario non cumpría os requisitos do servizo, polo que tivemos que afastarnos del.

Entón, aquí está o que decidín facer:

Copia a táboa e renomeala

Desde o paso anterior, decateime de que eliminar unha cantidade tan grande de datos crea unha carga igualmente grande. Entón decidín crear unha nova táboa desde cero usando insert e mover os datos que ía eliminar nela.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

Se fai que a nova táboa teña o mesmo tamaño que o anterior, a velocidade de procesamento de datos tamén debería ser 1/7 máis rápida.

Despois de crear a táboa e renomeala, comecei a usala como táboa mestra. Agora se deixo caer a táboa con 300 millóns de rexistros todo debería estar ben.
Descubrín que truncar ou soltar crea menos sobrecarga que eliminar e decidín usar este método.

Actuación

「Enviando unha solicitude」

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

"…"
"…"
"Em...?"

Acción 4

Pensei que a idea anterior funcionaría, pero despois de enviar a solicitude de inserción, apareceron varios erros. MySQL non perdoa.

Xa estaba tan canso que comecei a pensar que xa non quería facer isto.

Sentei e pensei e decateime de que quizais había demasiadas consultas de inserción por unha vez...
Tentei enviar unha solicitude de inserción para a cantidade de datos que debería procesar a base de datos en 1 día. Pasou!

Ben, despois diso seguimos enviando solicitudes para a mesma cantidade de datos. Dado que necesitamos eliminar os datos dun mes, repetimos esta operación unhas 35 veces.

Cambiar o nome dunha táboa

Aquí a sorte estivo do meu lado: todo foi ben.

Falta de alerta

A velocidade de procesamento por lotes aumentou.

Anteriormente este proceso levaba aproximadamente unha hora, agora leva uns 2 minutos.

Despois de estar seguro de que todos os problemas estaban resoltos, deixei caer 300 millóns de rexistros. Borrei a táboa e sentín renacer.

Resumo

Decateime de que faltaba o procesamento de rotación no procesamento por lotes, e ese era o principal problema. Este tipo de erro arquitectónico leva a unha perda de tempo.

Pensas na carga durante a replicación de datos ao eliminar rexistros da base de datos? Non sobrecarguemos MySQL.

Aqueles que estean ben versados ​​en bases de datos definitivamente non atoparán tal problema. Para o resto de vós, espero que este artigo fose útil.

Grazas por ler!

Estaremos moi contentos se nos digas se che gustou este artigo, se a tradución é clara, se che foi útil?

Fonte: www.habr.com

Engadir un comentario