mysql — удаление большого количества строк с ограничением (php nightly cron)

Не уверен, что лучший способ справиться с этим. Для моей конкретной ситуации у меня есть множество таблиц, в которых я хочу удалить все строки с отметкой времени, превышающей 3 месяца назад … она ведет записи только за последние 3 месяца.

Очень просто это будет примерно так:

//set binding cutoff timestamp
$binding = array(
'cutoff_time' => strtotime('-3 months')
);

//##run through all the logs and delete anything before the cutoff time

//app
$stmt = $db->prepare("DELETE
FROM app_logs
WHERE app_logs.timestamp < :cutoff_time
");
$stmt->execute($binding);

//more tables after this

Каждая таблица, из которой я собираюсь удалить, имеет столбец отметки времени, который индексируется. Я обеспокоен тем, что в будущем количество строк для удаления будет большим. Какова была бы лучшая практика для ограничения кусков в цикле? Все, что я могу придумать, это сделать начальный выбор, чтобы найти, есть ли строки, которые нужно удалить, затем запустить удаление, если есть … повторять, пока начальный не найдет никаких результатов. Это добавляет дополнительный запрос подсчета для каждой итерации цикла.

Какова стандартная / рекомендуемая практика здесь?

РЕДАКТИРОВАТЬ:

быстрое описание того, что я думал

//set binding cutoff timestamp
$binding = array(
'cutoff_time' => strtotime('-3 months')
);

//set limit value
$binding2 = array(
'limit' => 1000
);

//##run through all the logs and delete anything before the cutoff time

//get the total count
$stmt = $db->prepare("SELECT
COUNT(*)
FROM app_logs
WHERE app_logs.timestamp < :cutoff_time
");
$stmt->execute($binding);

//get total results count from above
$found_count = $stmt->fetch(PDO::FETCH_COLUMN, 0);

// loop deletes
$stmt = $db->prepare("DELETE
FROM app_logs
WHERE app_logs.timestamp < :cutoff_time
LIMIT :limit
");

while($found_count > 0)
{
$stmt->execute( array_merge($binding, $binding2) );

$found_count = $found_count - $binding2['limit'];
}

0

Решение

Это зависит от размера таблицы и ее рабочей нагрузки, поэтому вы можете попробовать несколько итераций:

  1. Просто удалите все, что старше 3 месяцев. Посмотрите, правильно ли выбрано время. Есть ли снижение производительности или блокировка таблиц? Как ваше приложение обрабатывает период удаления данных?

  2. В случае, если все плохо, подумайте об удалении с лимитом 10 Кб или около того. Проверьте это как указано выше. Добавьте правильные индексы

  3. Даже если это все еще плохо, подумайте о выборе PK перед удалением, а затем об удалении на PK с ограничением 10k и паузами между запросами.

  4. Все еще плохо? Добавьте новый столбец «удалить» и выполните над ним операции со всеми вышеуказанными требованиями.

Есть много хитростей для вращающихся столов. Попробуйте что-нибудь, и вы столкнетесь со своими потребностями

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]