Не уверен, что лучший способ справиться с этим. Для моей конкретной ситуации у меня есть множество таблиц, в которых я хочу удалить все строки с отметкой времени, превышающей 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'];
}
Это зависит от размера таблицы и ее рабочей нагрузки, поэтому вы можете попробовать несколько итераций:
Просто удалите все, что старше 3 месяцев. Посмотрите, правильно ли выбрано время. Есть ли снижение производительности или блокировка таблиц? Как ваше приложение обрабатывает период удаления данных?
В случае, если все плохо, подумайте об удалении с лимитом 10 Кб или около того. Проверьте это как указано выше. Добавьте правильные индексы
Даже если это все еще плохо, подумайте о выборе PK перед удалением, а затем об удалении на PK с ограничением 10k и паузами между запросами.
Все еще плохо? Добавьте новый столбец «удалить» и выполните над ним операции со всеми вышеуказанными требованиями.
Есть много хитростей для вращающихся столов. Попробуйте что-нибудь, и вы столкнетесь со своими потребностями
Других решений пока нет …