Назад к вопросам
Senior
9
В чём основная проблема данной реализации WITH archived_charges AS ( SELECT id, charging_station_id, start_time, end_time FROM charge_sessions WHERE end_time < current_date - interval '30' day ) INSERT INTO charges_history SELECT * FROM archived_charges; DELETE FROM charge_sessions USING archived_charges WHERE charge_sessions.start_time < current_date - interval '15' day;
Компании, где спрашивали
СБК ПАРУС
Ответ от нейросети
sobes.tech AI
Основная проблема в данной реализации — несогласованность условий выборки и удаления, а также потенциальная потеря данных и неэффективность.
Подробно:
-
Разные интервалы времени для выборки и удаления:
- В WITH выбираются сессии, завершённые более 30 дней назад.
- В DELETE удаляются сессии, начавшиеся более 15 дней назад.
Это значит, что некоторые сессии могут попасть в charges_history (архив), но не будут удалены из charge_sessions, либо наоборот — удаляться без архивации.
-
Отсутствие атомарности:
- INSERT и DELETE выполняются отдельными запросами, что может привести к рассогласованию данных при сбоях.
-
Использование DELETE с USING и условием по start_time, а не по id из archived_charges:
- Это может привести к удалению не тех строк, которые были архивированы.
Для исправления нужно:
- Использовать одинаковые условия для выборки и удаления.
- Выполнить операции в одной транзакции.
- Удалять именно те записи, которые были вставлены в архив, например, по id.
Пример исправления:
WITH archived_charges AS (
DELETE FROM charge_sessions
WHERE end_time < current_date - interval '30' day
RETURNING *
)
INSERT INTO charges_history
SELECT * FROM archived_charges;
Так мы сначала удаляем нужные записи, сразу возвращая их для вставки в архив, обеспечивая консистентность и атомарность.