Как хранить и извлекать часы работы врача в базе данных?

#sql #performance #cassandra #schedule #scylla

#sql #Производительность #кассандра #Расписание #сцилла

Вопрос:

Как сохранить рабочее время врача в базе данных, чтобы эффективно извлекать свободные временные интервалы?

Подходы

A. Правила и исключения магазина

  • врач определяет рабочее время, например, с 9 утра до 3 часов дня каждые 30 минут с перерывом 11-12
  • врач определяет исключения, например, отпуск с 1/1/22 по 1/14/22
  • врач определяет другие исключения, например, завтра с 8:30 утра до 12:30 вечера
  • каждый раз, когда пациент хочет записаться на прием, сервер извлекает все правила для врача из базы данных, анализирует их и возвращает свободные временные интервалы (например, 9 утра, 9:30 утра, 11:30 утра).
  • нам нужны приоритетные/иерархические правила и исключения (они могут перекрываться)?

B. Заполните все временные интервалы в базе данных

  • врач определяет рабочее время, например, с 9 утра до 3 часов дня каждые 30 минут с перерывом 11-12
  • если завтра доктор недоступен, он просто удаляет временные интервалы с завтрашнего дня
  • если врач будет доступен завтра с 8:30 утра, он переместит блок временных интервалов
  • каждый временной интервал = строка в базе данных
  • каждый раз, когда пациент хочет записаться на прием, сервер извлекает все временные интервалы из базы данных за указанный период времени и не нуждается в анализе правил
  • нам нужно отслеживать изменения, если мы хотим их отменить?
  • мы не можем заполнять временные интервалы вечно — врач должен планировать расписание на определенное количество времени (например, на следующий месяц), или временные интервалы должны создаваться на основе правил (гибридный подход A B) автоматически с помощью задания cron

Примеры исключений

  • отпуск
    • в случае, если нам нужно сделать исключение или разделить правила на 2 отдельных (до и после отпуска)
    • в B мы просто удаляем временные интервалы из базы данных для отпуска
  • измените часы операции на определенный период времени, например, на следующей неделе
    • в аналогичном, как описано выше, мы делаем исключение или разделяем правила
    • в разделе B мы меняем временные интервалы только на следующую неделю, а остальные остаются неизменными
  • измените часы операции навсегда
    • в аналогичном, как описано выше, мы делаем исключение или разделяем правила
    • в B мы меняем все временные интервалы до конца
  • в нечетные недели врач работает: Пн, Ср, Пт; в четные недели: Вт, Чт, Сб
    • в результате правила усложняются, и разбор может занять больше времени
    • в B мы заполняем временные интервалы в базе данных только один раз в соответствии с заданным алгоритмом
  • врач меняет время отпуска или удаляет исключение
    • in A he just changes exception time period or deletes and exception
    • in B we populate back time slots (system should track changes to undo them?)
  • some slots may be larger (e.g. 1 hour) than others (e.g. 30 minutes), e.g. for a procedure

Schema examples

A. Rules and exceptions

 create table rules (  doctor_id UUID,  rule_id UUID,  priority tinyint, -- example approach to solve overlapping rules  base_rule UUID, -- another approach is a tree of rules  time_from timestamp, -- rule is valid from this time (required)  time_to timestamp, -- rule is valid until this time (null if forever)  days tinyint, -- bitwise (1-Mon, 2-Tue, 4-Wed, etc)  app_time tinyint, -- appointment time (in minutes, e.g. 30)  start_hour tinyint, -- e.g. 8 AM (when he wants to see first patient)  end_hour tinyint, -- e.g. 15 PM (when he leaves surgery / logs out)  hours listlt;timegt;,-- another approach is a list with all hours (8, 8:30, 9, etc)  primary key (doctor_id, rule_id) );  

Мы тоже хотим исключений? Возможно, но мы также можем использовать rules с приоритетами или деревом правил.

 create table rules (  doctor_id UUID,  exception_id UUID,  reason TEXT,  -- all fields similar as in rules table  primary key (doctor_id, exception_id) );  

B. Заполните все временные интервалы в базе данных

 create table rules (  doctor_id UUID,  patient_id UUID, -- null if free, not null if booked by a patient  slot_from timestamp, -- time slot start time (required, e.g. 1/1/22 9:00)  slot_to timestamp, -- time slot end time (required, e.g. 1/1/22 9:30)  primary key (doctor_id, slot_from) );  

Просто! Никакого анализа правил/исключений, просто извлекайте и возвращайте временные интервалы пациенту.

Подводить итоги

  1. Какой подход лучше всего подходит?
  2. Если какой — либо подход плох- почему?
  3. Что бы вы изменили для повышения производительности и гибкости?
  4. Если подход А, как наиболее эффективно обрабатывать изменения, исключения и т.д.?
  5. Как это реализовано в уже существующих календарях/расписаниях, системах встреч и т.д.?

Комментарии:

1. Трудно сказать, не зная, как будет запрашиваться эта таблица. Неужели это действительно будет только когда-нибудь doctor_id ?

2. @Aaron: по doctor_id в подходе A или по (doctor_id, slot_from) в подходе B. Мы всегда будем включать doctor_id в запрос. Нам нужно отобразить свободные временные интервалы на определенный период времени (например, следующие 5 дней) или на месяц.