Database
 sql >> база данни >  >> RDS >> Database

Отново и отново! Управление на повтарящи се събития в модел на данни

Повтарящо се събитие, по дефиниция, е събитие, което се повтаря на интервал; нарича се още периодично събитие. Има много приложения, които позволяват на своите потребители да настройват повтарящи се събития. Как системата за база данни управлява повтарящи се събития? В тази статия ще разгледаме един начин, по който се обработват.

Повтарянето не е лесно за приложенията да се справят. Това може да се превърне в ураганна задача, особено когато става въпрос за покриване на всеки възможен повтарящ се сценарий – включително създаване на събития на две седмици или тримесечие или позволяване на разсрочване на всички бъдещи случаи на събитие.

Два начина за управление на повтарящи се събития

Мога да се сетя за поне два начина за справяне с периодични задачи в модел на данни. Преди да ги обсъдим, нека бързо да разгледаме изискванията на тази задача. Накратко, ефективното управление означава:

  • На потребителите е разрешено да създават редовни и повтарящи се събития.
  • Ежедневни, седмични, двуседмични, месечни, тримесечни, двугодишни и годишни събития могат да се създават без ограничения за крайна дата.
  • Потребителите могат да пренасрочват или отменят екземпляр на събитие или всички бъдещи екземпляри на събитие.

Имайки предвид тези параметри, идват на ум два начина за управление на повтарящи се събития в модела на данни. Ще ги наречем наивен и експертен начин.

Наивният начин: Съхраняване на всички възможни повтарящи се екземпляри на събитие като отделни редове в таблица. В това решение се нуждаем само от една таблица, а именно event . Тази таблица има колони като event_title , start_date , end_date , is_full_day_event и т.н. start_date и end_date колоните са типове данни за времеви отпечатъци; по този начин те могат да приемат събития, които не продължават цял ​​ден.

Плюсовете: Това е доста ясен подход и най-простият за изпълнение.

Против: Наивният начин има някои значителни недостатъци, включително:

  • Необходимостта от съхраняване на всички възможни екземпляри на събитие. Ако имате предвид нуждите на голяма потребителска база, тогава е необходимо голямо пространство. Пространството обаче е доста евтино, така че тази точка няма голямо влияние.
  • Много объркан процес на актуализиране. Да предположим, че събитие е пренасрочено. В този случай някой трябва да актуализира всички негови екземпляри. При разсрочване трябва да се извършат огромен брой DML операции, което създава отрицателно въздействие върху производителността на приложението.
  • Обработка на изключения. Всички изключения трябва да се обработват грациозно, особено ако трябва да се върнете и да редактирате първоначалната среща, след като направите изключение. Например, да предположим, че премествате третия екземпляр на повтарящо се събитие напред с един ден. Ами ако впоследствие редактирате часа на първоначалното събитие? Вмъквате ли отново друго събитие в първоначалния ден и оставяте това, което сте посочили? Прекратяване на връзката на изключението? Опитайте да го промените по подходящ начин?
  • Експертният начин: Съхраняване на повтарящ се модел и програмно генериране на минали и бъдещи екземпляри на събития. Това решение разглежда недостатъците на наивното решение. Ще обясним подробно експертното решение в тази статия.

    Предложеният модел




    Създаване на събития

    Всички планирани събития, независимо от техния редовен или повтарящ се характер, се регистрират в event маса. Не всички събития са повтарящи се събития, така че ще ни трябва колона за флаг, is_recurring , в тази таблица, за да посочите изрично повтарящи се събития. event_title и event_description колони съхраняват темата и кратко резюме на събитията. Описанията на събития не са задължителни, поради което тази колона може да бъде нула.

    Както подсказват имената им, start_date и end_date колоните запазват началната и крайната дата на събитията. В случай на редовни събития, тези колони съхраняват действителните начални и крайни дати. Те обаче също така съхраняват датите на първото и последното появяване на периодични събития. Ще запазим end_date колона като нула, тъй като потребителите могат да конфигурират повтарящи се събития без крайна дата. В този случай бъдещите събития до хипотетична крайна дата (да речем за една година) ще бъдат показани в потребителския интерфейс.

    is_full_date_event колона означава дали дадено събитие е целодневно събитие. В случай на целодневно събитие, start_time и end_time колоните ще бъдат нулеви; това е причината и двете колони да са нулеви.

    created_by и created_date колоните съхраняват кой потребител е създал събитие и датата на създаването на събитието.

    Следва parent_event_id колона. Това играе основна роля в нашия модел на данни. Ще обясня значението му по-късно.

    Управление на повторенията

    Сега стигаме направо до основната формулировка на проблема:Ами ако се създаде повтарящо се събитие в event таблица – т.е. is_recurring флагът за събитието е „Y“?

    Както беше обяснено по-рано, ние ще съхраняваме повтарящ се модел за събития, така че да можем да конструираме всички негови бъдещи събития. Нека започнем със създаване на recurring_pattern маса. Тази таблица има следните колони:

    • Event_id – Тази колона се препраща от event таблица и действа като първичен ключ в тази таблица. Показва идентифициращата връзка между event и recurring_pattern маси. Тази колона също така ще гарантира, че има максимум един повтарящ се модел за всяко събитие.
    • Recurring_type_id – Тази колона обозначава вида на повторението, независимо дали е ежедневно, седмично, месечно или годишно.
    • Max_num_of_occurrances – Има моменти, когато не знаем точната крайна дата за дадено събитие, но знаем колко събития (срещи) са необходими, за да се завърши. Тази колона съхранява произволно число, което определя логическия край за събитие.
    • Separation_count – Може да се чудите как може да се конфигурира двуседмично или двугодишно събитие, ако има само четири възможни стойности от тип повтаряне (дневно, седмично, месечно, годишно). Отговорът е separation_count колона. Тази колона означава интервала (в дни, седмици или месеци), преди да бъде разрешено следващото събитие. Например, ако събитие трябва да бъде конфигурирано за всяка друга седмица, тогава separation_count =“1” за да отговори на това изискване. Стойността по подразбиране за тази колона е „0“.

    Нека разгледаме значението на останалите колони по отношение на различните видове повторения.

    Ежедневно повтаряне

    Наистина ли трябва да улавяме модел за ежедневно повтарящо се събитие? Не, защото всички подробности, необходими за генериране на ежедневен модел на повторение, вече са регистрирани в event таблица.

    Единственият сценарий, който изисква модел, е, когато събитията са насрочени за алтернативни дни или на всеки X брой дни. В този случай separation_count колона ще ни помогне да разберем модела на повторение и да извлечем допълнителни случаи.

    Ежеседмично повтаряне

    Необходима ни е само една допълнителна колона, day_of_week , за да запаметите кой ден от седмицата ще се проведе това събитие. Ако приемем, че понеделник е първият ден от седмицата, а неделята е последният, възможните стойности биха били 1,2,3,4,5,6 и 7. При необходимост трябва да се направят подходящи промени в кода, който генерира отделни събития. Всички останали колони ще бъдат нулеви за седмични събития.

    Да вземем класически тип седмично събитие:двуседмичното събитие. В този случай ще кажем, че се случва всяка алтернативна седмица във вторник, вторият ден от седмицата. И така:

    • recurring_type_id ще бъде „седмично“.
    • separation_count ще бъде „1“.
    • day_of_week ще бъде „2“.

    Месечно повтаряне

    Освен day_of_week , изискваме още две колони, за да изпълним всеки сценарий на месечно повтаряне. Накратко, тези колони са:

    • Week_of_month – Тази колона е за събития, които са планирани за определена седмица от месеца – т.е. първа, втора, последна, предпоследна и т.н. Можем да съхраняваме тези стойности като 1,2,3, 4,.. (от началото на месеца) или -1,-2,-3,... (от края на месеца).
    • Day_of_month – Има случаи, когато събитие е насрочено за определен ден от месеца, да речем 25-и. Тази колона отговаря на това изискване. Като week_of_month , може да се попълни с положителни числа („7“ за 7-ия ден от началото на месеца) или с отрицателни числа ( „-7“ за седмия ден от края на месеца).

    Нека сега разгледаме по-сложен пример - тримесечно събитие. Да предположим, че една компания планира тримесечно събитие за прогнозиране на резултата за 11-ия ден от първия месец на всяко тримесечие (обикновено януари, април, юли и октомври). Така че в този случай:

    • recurring_type_id ще бъде „ежемесечно“.
    • separation_count ще бъде „2“.
    • day_of_month ще бъде „11“.
    • Всички останали колони ще бъдат нулеви.

    В горния пример приемаме, че потребителят създава тримесечната прогноза за резултата през януари. Моля, имайте предвид, че тази логика на разделяне ще започне да се брои от месеца, седмицата или деня, когато е създадено събитието.

    На подобни линии, полугодишните събития могат да се регистрират като месечни с separation_count от „5“.

    Ежегодно повтаряне

    Годишното повтаряне е доста лесно. Имаме колони за определени дни от седмицата и месеца, така че се нуждаем само от една допълнителна колона за месеца от годината. Нарекли сме тази колона month_of_year .

    Обработка на изключения от повтарящи се събития

    Сега да стигнем до изключенията. Ами ако конкретен случай на повтарящо се събитие бъде отменен или пренасрочен? Всички такива случаи се регистрират отделно в event_instance_exception маса.

    Нека да разгледаме две колони, Is_rescheduled и is_cancelled . Тези колони означават дали този екземпляр е пренасрочен за по-късна дата/час или е отменен изцяло. Защо имам две отделни колони за това? Е, просто помислете за събития, които първо са били разсрочени и след това напълно отменени. Това се случва и ние имаме начин да го запишем с тези колони.

    Освен тези две колони, всички останали колони действат по същия начин като в event таблица.

    Защо да свързвате две събития чрез parent_event_id ?

    Има приложения, които позволяват на потребителите да пренасрочват всички бъдещи случаи на повтарящо се събитие. В такива случаи имаме две възможности. Можем да съхраняваме всички бъдещи екземпляри в event_instance_exception (намек:не е приемливо решение). Или можем да създадем ново събитие с нови параметри за дата/час в event таблица и я свържете с нейното по-ранно събитие (родителското събитие) посредством id_parent_event колона.

    С това решение можем да получим всички минали събития на събитие, дори когато моделът му на повторение е променен.

    Как да подобрим обработката на повтарящи се събития?

    Има някои по-сложни области около повтарящи се събития, които не сме обсъждали. Ето две:

    • Събития, които се случват на празници. Когато конкретен случай на събитие се случи на официален празник, трябва ли той автоматично да бъде преместен в работния ден непосредствено след празника? Или трябва да се отмени автоматично? При какви обстоятелства би се приложило едно от тези?
    • Конфликти между събития. Ами ако определени събития (които се изключват взаимно) паднат в един и същи ден?

    Какви промени трябва да направим, за да изградим тези възможности? Моля, кажете ни вашите мнения в секцията за коментари.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Промяна на голяма маса в RDS Решение за пълна грешка на таблицата

  2. Топ 10 причини защо трябва да научите SQL

  3. Решения за читатели за предизвикателството на специалните острови

  4. Вашият ODBC драйвер поддържа ли потребителски източници на данни?

  5. Забавление с компресия (columnstore) на много голяма маса – част 3