Sobes.tech
Назад к вопросам
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

Основная проблема в данной реализации — несогласованность условий выборки и удаления, а также потенциальная потеря данных и неэффективность.

Подробно:

  1. Разные интервалы времени для выборки и удаления:

    • В WITH выбираются сессии, завершённые более 30 дней назад.
    • В DELETE удаляются сессии, начавшиеся более 15 дней назад.

    Это значит, что некоторые сессии могут попасть в charges_history (архив), но не будут удалены из charge_sessions, либо наоборот — удаляться без архивации.

  2. Отсутствие атомарности:

    • INSERT и DELETE выполняются отдельными запросами, что может привести к рассогласованию данных при сбоях.
  3. Использование 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;

Так мы сначала удаляем нужные записи, сразу возвращая их для вставки в архив, обеспечивая консистентность и атомарность.