Выбор ответа Senior Индексы обновлено

Запретить пересекающиеся бронирования в базе

Вопрос

Таблица bookings(room_id int, during tstzrange). Как гарантировать на уровне базы, что одну комнату нельзя забронировать на пересекающееся время?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: EXCLUDE USING gist (roomid WITH =, during WITH &&). Exclusion-ограничение обобщает уникальность: запрещает две строки, для которых все перечисленные операторы истинны, то есть та же комната и пересекающиеся (&&) интервалы.

Варианты ответа

  1. UNIQUE (room_id, during) с индексом по диапазону
  2. Триггер с SELECT на пересечения перед вставкой (Read Committed)
  3. EXCLUDE USING gist (room_id WITH =, during WITH &&)правильный ответ
  4. B-tree индекс по (room_id, lower(during), upper(during))

Разбор

Exclusion-ограничение обобщает уникальность: запрещает две строки, для которых все перечисленные операторы истинны, то есть та же комната и пересекающиеся (&&) интервалы. Оно строится на GiST, а чтобы GiST умел обычное равенство по int, подключают расширение btree_gist. UNIQUE поймает только полностью совпадающие интервалы. Триггер с проверкой через SELECT на Read Committed пропустит гонку: две транзакции одновременно не увидят друг друга и обе вставят. B-tree не умеет проверять пересечение диапазонов.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.