Массовое удаление для большой таблицы в MySQL

9

У меня есть таблица уведомлений, содержащая около 100 миллионов строк хоста в Amazon RDS с 1000 IOPS, и я хочу удалить эти строки старше одного месяца.

Если я это сделаю DELETE FROM NOTIFICATION WHERE CreatedAt < DATE_SUB(CURDATE(), INTERVAL 30 day);, все IOPS будут приняты, процесс займет несколько часов, и много новых записей не могут быть вставлены из-за «Превышено время ожидания блокировки; попробуйте перезапустить транзакцию».

Я пытался сделать так, как описано здесь: http://mysql.rjweb.org/doc.php/deletebig Однако я использую UUID вместо ID приращения.

Как правильно и эффективно удалить эти строки, не влияя на добавление / обновление новых данных?

Тяньи Конг
источник
Вы правы ypercube, я должен исправить это. Спасибо за указание!
Tianyi Cong
Удаление записей меньшими порциями, не влияет на операцию вставки, я попробовал это с циклом, и он заканчивает удаление 70 миллионов записей менее чем за час. Rathishkumar.in/2017/12/…
Rathish

Ответы:

11

Создайте временную таблицу, включите и выключите ее и скопируйте в нее данные за последние 30 дней.

#
# 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);

В нерабочее время бросьте старый стол

DROP TABLE NOTIFICATION_OLD;

Вот преимущества этого УДАЛЕНИЯ, как это

  1. NOTIFICATION быстро опорожняется путем переключения в пустую таблицу.
  2. NOTIFICATION немедленно доступен для новых вставок
  3. Оставшиеся 30 дней добавляются обратно, в NOTIFICATIONто время как новые INSERT могут иметь место.
  4. Удаление старой версии NOTIFICATIONне мешает новым INSERT
  5. ПРИМЕЧАНИЕ: я рекомендовал делать приманку и переключение для таблиц DELETE до: (см. Мой пост от 19 июля 2012 года: Оптимизация запроса DELETE в таблице MySQL MEMORY )

Попробуйте!

RolandoMySQLDBA
источник
Спасибо, ответ Роландо! Как MySql внутренне обрабатывает дроп-таблицу? Сначала удалите все столбцы, затем удалите таблицу или что-то еще? Это займет намного меньше времени, чем удаление этих облачков?
Тяньи Конг
Я применяю эту стратегию при подготовке. Должна ли команда переименования начинаться с "RENAME TABLE"?
Тяньи Конг
будет ли какая-то разница, если я буду использовать его внутри блока транзакции, имея в виду тайм-аут ожидания блокировки, а также будет ли у него какие-либо минусы, если моя фактическая таблица станет действительно огромной, которая теперь переименована и должна быть отброшена
Мухаммед Омер Аслам
1
@MuhammadOmerAslam в этом случае файл ibdata1 (системное табличное пространство) будет просто расти в журналах отмены. Это особенно касается случая, когда размер файла ibdata1 начинает увеличиваться (см. Мой старый пост dba.stackexchange.com/questions/40730/… ). Вы должны проявлять большую осторожность, используя pt-archiver, как упомянуто в ответе akuzminsky. Можно было бы ограничить удаление строк в кусках, а затем использовать pt-online-schema-change для запуска, ALTER TABLE ENGINE=InnoDB чтобы уменьшить таблицу.
RolandoMySQLDBA
1
@MuhammadOmerAslam Вышеуказанный подход будет идеальным, если вы запланировали время простоя. По ссылке в ответе акузминского ( percona.com/doc/percona-toolkit/LATEST/pt-archiver.html ). Вы можете использовать pt-archiver для архивирования данных или просто удалить данные без архивации.
RolandoMySQLDBA
3

Мой любимый это pt-archiver от Percona Toolkit. Он заботится о загрузке MySQL, задержке репликации.

akuzminsky
источник
Спасибо, ответ акузминский! Я буду смотреть в него. Раньше я давал Percona попытку изменить таблицу уведомлений с помощью pt-online-schema-change. Однако для внесения изменений требовалась привилегия SUPER, которая не предоставляется RDS. Кстати, вы знаете какой-нибудь хороший способ изменить огромный стол?
Тяньи Конг
@Tianyi Если у вас есть новый вопрос: пожалуйста, задайте его как новый вопрос и, возможно, прокомментируйте здесь со ссылкой, не задавайте его в комментариях, это не так, как работает этот сайт.
Джек говорит, попробуйте topanswers.xyz
-2

создать таблицу уведомлений_темпов как выберите * из уведомления, где CreatedAt <DATE_SUB (CURDATE (), ИНТЕРВАЛ 30 дней);

уведомление об удалении таблицы;

ПЕРЕИМЕНОВАТЬ извещение_повестку В УВЕДОМЛЕНИЕ;

user52557
источник
И это не повлияет на добавление / обновление новых данных? Я так не думаю.
Colin 't Hart
Этот метод имеет 2 проблемы: 1) делает NOTIFICATION недоступным в течение DROP TABLE. 2) ВСТАВКИ, которые происходят во время CREATE TABLEпропуска.
RolandoMySQLDBA
Еще одна проблема: надо сказатьRENAME TABLE notification_temp ...
RolandoMySQLDBA