Я бы порекомендовал вам попытаться удалить фиксированное количество строк одновременно. Я еще не использовал mysql, но вот пример из MS SQL.
DECLARE @DELETE_COUNT INT, @ARCHVIE_DATE DATETIME
SET @ARCHIVE_DATE = '2010-10-01'
SET @DELETE_COUNT = 1000
WHILE (@DELETE_COUNT <> 0)
BEGIN
DELETE TOP (@DELETE_COUNT)
OUTPUT DELETED.*
INTO MyArchiveTable
FROM MyTable a
WHERE a.PrescriptionDate < @ARCHIVE_DATE
SET @DELETE_COUNT = @@ROWCOUNT
END
Преимущество заключается в удалении и архивировании данных в одном операторе. Если MySQL не имеет ничего подобного, ваш план вполне разумен. Вам необходимо сохранить первые 1000 строк, а затем удалить их. Пожалуйста, убедитесь, что у вас есть заказ на ... в случае, если кто-то изменяет кластерный индекс на вас и, очевидно, индекс на PrescriptionDate . Если возможно, вы можете создать кластерный индекс для PrescriptionDate. Или Вы можете добавить дату рецепта в существующий кластерный индекс в качестве первого столбца.
DECLARE @DELETE_COUNT INT, @ARCHVIE_DATE DATETIME
SET @ARCHIVE_DATE = '2010-10-01'
SET @DELETE_COUNT = 1000
WHILE (@DELETE_COUNT <> 0)
BEGIN
BEGIN TRANSACTION
INSERT INTO MyArchiveTable
SELECT TOP(@DELETE_COUNT) * FROM MyTable a WHERE a.PrescriptionDate < @ARCHIVE_DATE
ORDER BY a.PrescriptionDate
DELETE FROM MyTable a INNER JOIN
(SELECT TOP(@DELETE_COUNT) * FROM MyTable
WHERE PrescriptionDate < @ARCHIVE_DATE ORDER BY PrescriptionDate) b ON a.Id = b.Id
SET @DELETE_COUNT = @@ROWCOUNT
COMMIT TRANSACTION
END
Это также имеет дополнительное преимущество - не откатывать весь процесс удаления в случае тупика. Если в MySQL есть операторы try / catch, вы можете использовать их для перехвата ошибок взаимоблокировки, а затем их игнорировать. Цикл while должен повторяться снова и снова до тех пор, пока он не будет успешным.
Обратите внимание, что я никогда не использовал MySQL, поэтому мой синтаксис может быть неправильным.
Надеюсь, это поможет.