sql >> Database >  >> RDS >> Database

Opnieuw en opnieuw! Terugkerende gebeurtenissen in een gegevensmodel beheren

Een terugkerende gebeurtenis is per definitie een gebeurtenis die met een interval terugkeert; het wordt ook wel een periodieke gebeurtenis genoemd. Er zijn veel applicaties waarmee gebruikers terugkerende evenementen kunnen instellen. Hoe beheert een databasesysteem terugkerende gebeurtenissen? In dit artikel onderzoeken we een manier waarop ze worden afgehandeld.

Herhaling is niet gemakkelijk voor toepassingen om te gaan met. Het kan een orkaantaak worden, vooral als het gaat om het afdekken van elk mogelijk terugkerend scenario - inclusief het creëren van tweewekelijkse of driemaandelijkse evenementen of het opnieuw plannen van alle toekomstige evenementen.

Twee manieren om terugkerende gebeurtenissen te beheren

Ik kan tenminste twee manieren bedenken om periodieke taken in een datamodel af te handelen. Laten we, voordat we ze bespreken, snel de vereisten van deze taak doornemen. In een notendop, effectief beheer betekent:

  • Gebruikers mogen regelmatige en terugkerende evenementen maken.
  • Dagelijkse, wekelijkse, tweewekelijkse, maandelijkse, driemaandelijkse, tweejaarlijkse en jaarlijkse evenementen kunnen worden gemaakt zonder beperkingen op de einddatum.
  • Gebruikers kunnen een instantie van een evenement of alle toekomstige instanties van een evenement opnieuw plannen of annuleren.

Rekening houdend met deze parameters, denk je aan twee manieren om terugkerende gebeurtenissen in het gegevensmodel te beheren. We noemen ze de naïeve manier en de deskundige manier.

De naïeve manier: Het opslaan van alle mogelijke terugkerende instanties van een gebeurtenis als afzonderlijke rijen in een tabel. In deze oplossing hebben we slechts één tabel nodig, namelijk event . Deze tabel heeft kolommen zoals event_title , start_date , end_date , is_full_day_event , enz. De start_date en end_date kolommen zijn tijdstempelgegevenstypen; op deze manier kunnen ze evenementen accommoderen die niet de hele dag duren.

De pluspunten: Dit is een vrij eenvoudige benadering en de eenvoudigste om te implementeren.

De nadelen: De naïeve manier heeft een aantal belangrijke nadelen, waaronder:

  • De noodzaak om alle mogelijke instanties van een gebeurtenis op te slaan. Als u rekening houdt met de behoeften van een groot aantal gebruikers, is een groot stuk ruimte vereist. Ruimte is echter vrij goedkoop, dus dit punt heeft geen grote impact.
  • Een erg rommelig updateproces. Stel dat een evenement wordt verplaatst. In dat geval moet iemand alle exemplaren ervan bijwerken. Er moeten enorme aantallen DML-bewerkingen worden uitgevoerd bij het opnieuw plannen, wat een negatief effect heeft op de applicatieprestaties.
  • Behandelen van uitzonderingen. Alle uitzonderingen moeten netjes worden afgehandeld, vooral als u terug moet gaan en de oorspronkelijke afspraak moet bewerken nadat u een uitzondering hebt gemaakt. Stel dat u het derde exemplaar van een terugkerende gebeurtenis een dag vooruit schuift. Wat als u vervolgens de tijd van de oorspronkelijke gebeurtenis wijzigt? Voegt u een andere gebeurtenis op de oorspronkelijke dag opnieuw toe en laat u de gebeurtenis die u naar voren bracht, achterwege? De uitzondering ontkoppelen? Probeer het op de juiste manier te veranderen?
  • De deskundige manier: Het opslaan van een terugkerend patroon en het programmatisch genereren van eerdere en toekomstige gebeurtenisinstanties. Deze oplossing pakt de nadelen van de naïeve oplossing aan. We zullen de expertoplossing in detail uitleggen in dit artikel.

    Het voorgestelde model




    Evenementen maken

    Alle geplande evenementen, ongeacht hun reguliere of terugkerende karakter, worden vastgelegd in het event tafel. Niet alle evenementen zijn terugkerende evenementen, dus we hebben een vlagkolom nodig, is_recurring , in deze tabel om terugkerende gebeurtenissen expliciet op te geven. De event_title en event_description kolommen slaan het onderwerp op en een korte samenvatting van gebeurtenissen. Gebeurtenisbeschrijvingen zijn optioneel, daarom is deze kolom nullable.

    Zoals hun namen doen vermoeden, is de start_date en end_date kolommen bevatten de begin- en einddatum van gebeurtenissen. In het geval van reguliere evenementen slaan deze kolommen de werkelijke start- en einddatum op. Ze slaan echter ook de datums op van de eerste en laatste keer dat periodieke gebeurtenissen plaatsvinden. We behouden de end_date kolom als nullable, aangezien gebruikers terugkerende gebeurtenissen zonder einddatum kunnen configureren. In dit geval worden toekomstige gebeurtenissen tot een hypothetische einddatum (bijvoorbeeld een jaar) weergegeven in de gebruikersinterface.

    Het is_full_date_event kolom geeft aan of een evenement een evenement van een hele dag is. In het geval van een evenement dat een hele dag duurt, wordt de start_time en end_time kolommen zouden null zijn; dat is de reden om beide kolommen nullable te houden.

    De created_by en created_date kolommen slaan op welke gebruiker een evenement heeft gemaakt en de datum waarop dat evenement is gemaakt.

    Vervolgens is er de parent_event_id kolom. Dit speelt een grote rol in ons datamodel. De betekenis ervan zal ik later uitleggen.

    Herhalingen beheren

    Nu komen we meteen bij de belangrijkste probleemstelling:wat als een terugkerende gebeurtenis wordt gemaakt in de event tabel – d.w.z. de is_recurring vlag voor het evenement is "Y"?

    Zoals eerder uitgelegd, zullen we een terugkerend patroon voor gebeurtenissen opslaan, zodat we al zijn toekomstige gebeurtenissen kunnen construeren. Laten we beginnen met het maken van het recurring_pattern tafel. Deze tabel heeft de volgende kolommen:

    • Event_id – Deze kolom is afkomstig van het event tabel, en het fungeert als de primaire sleutel in deze tabel. Het toont de identificerende relatie tussen event en recurring_pattern tafels. Deze kolom zorgt er ook voor dat er maximaal één terugkerend patroon bestaat voor elke gebeurtenis.
    • Recurring_type_id – Deze kolom geeft het type herhaling aan, of het nu dagelijks, wekelijks, maandelijks of jaarlijks is.
    • Max_num_of_occurrances – Er zijn momenten waarop we de exacte einddatum van een evenement niet weten, maar we weten wel hoeveel gebeurtenissen (vergaderingen) er nodig zijn om het te voltooien. In deze kolom wordt een willekeurig getal opgeslagen dat het logische einde van een gebeurtenis definieert.
    • Separation_count – U vraagt ​​zich misschien af ​​hoe een tweewekelijkse of tweejaarlijkse gebeurtenis kan worden geconfigureerd als er slechts vier mogelijke herhalingswaarden zijn (dagelijks, wekelijks, maandelijks, jaarlijks). Het antwoord is de separation_count kolom. Deze kolom geeft het interval aan (in dagen, weken of maanden) voordat de volgende gebeurtenisinstantie is toegestaan. Als een evenement bijvoorbeeld om de week moet worden geconfigureerd, dan separation_count ="1" om aan deze eis te voldoen. De standaardwaarde voor deze kolom is "0".

    Laten we eens kijken naar de betekenis van de resterende kolommen in termen van de verschillende soorten recidieven.

    Dagelijkse herhaling

    Moeten we echt een patroon vastleggen voor een dagelijks terugkerend evenement? Nee, want alle details die nodig zijn om een ​​dagelijks herhalingspatroon te genereren, zijn al vastgelegd in het event tafel.

    Het enige scenario dat een patroon vereist, is wanneer gebeurtenissen worden gepland om andere dagen of om de X aantal dagen. In dit geval is de separation_count kolom zal ons helpen het herhalingspatroon te begrijpen en verdere instanties af te leiden.

    Wekelijkse herhaling

    We hebben slechts één extra kolom nodig, day_of_week , om op te slaan op welke dag van de week dit evenement zal plaatsvinden. Ervan uitgaande dat maandag de eerste dag van de week is en zondag de laatste, zijn de mogelijke waarden 1,2,3,4,5,6 en 7. Indien nodig moeten de nodige wijzigingen worden aangebracht in de code die afzonderlijke gebeurtenissen genereert. Alle overige kolommen zijn null voor wekelijkse evenementen.

    Laten we een klassiek soort wekelijkse gebeurtenis nemen:de tweewekelijkse gebeurtenis. In dit geval zeggen we dat het elke andere week op een dinsdag, de tweede dag van de week, gebeurt. Dus:

    • De recurring_type_id zou "wekelijks" zijn.
    • De separation_count zou "1" zijn.
    • De day_of_week zou "2" zijn.

    Maandelijks herhaling

    Naast day_of_week , hebben we nog twee kolommen nodig om te voldoen aan elk maandelijks herhalingsscenario. In het kort zijn deze kolommen:

    • Week_of_month – Deze kolom is voor evenementen die zijn gepland voor een bepaalde week van de maand - d.w.z. de eerste, tweede, laatste, voorlaatste, etc. We kunnen deze waarden opslaan als 1,2,3, 4,.. (geteld vanaf het begin van de maand) of -1,-2,-3,... (gerekend vanaf het einde van de maand).
    • Day_of_month – Er zijn gevallen waarin een evenement is gepland op een bepaalde dag van de maand, bijvoorbeeld de 25e. Deze kolom voldoet aan deze eis. Like week_of_month , het kan worden gevuld met positieve getallen ("7" voor de 7e dag vanaf het begin van de maand) of negatieve getallen ("-7" voor de zevende dag vanaf het einde van de maand).

    Laten we nu een ingewikkelder voorbeeld bekijken:een driemaandelijks evenement. Stel dat een bedrijf een kwartaalresultaatprojectie-evenement plant voor de 11e dag van de eerste maand van elk kwartaal (meestal januari, april, juli en oktober). Dus in dit geval:

    • De recurring_type_id zou "maandelijks" zijn.
    • De separation_count zou "2" zijn.
    • De day_of_month zou "11" zijn.
    • Alle resterende kolommen zijn null.

    In het bovenstaande voorbeeld gaan we ervan uit dat de gebruiker de kwartaalresultaatprognose in januari maakt. Houd er rekening mee dat deze scheidingslogica begint te tellen vanaf de maand, week of dag waarop de afspraak is gemaakt.

    Op dezelfde manier kunnen halfjaarlijkse evenementen worden vastgelegd als maandelijkse evenementen met een separation_count van “5”.

    Jaarlijks herhaling

    Jaarlijkse herhaling is vrij eenvoudig. We hebben kolommen voor bepaalde dagen van de week en de maand, dus we hebben slechts één extra kolom nodig voor de maand van het jaar. We hebben deze kolom de naam month_of_year .

    Uitzonderingen van terugkerende gebeurtenissen afhandelen

    Laten we nu naar de uitzonderingen gaan. Wat als een bepaald geval van een terugkerend evenement wordt geannuleerd of verplaatst? Al dergelijke instanties worden afzonderlijk geregistreerd in de event_instance_exception tafel.

    Laten we eens kijken naar twee kolommen, Is_rescheduled en is_cancelled . Deze kolommen geven aan of deze instantie wordt verplaatst naar een latere datum/tijd of helemaal wordt geannuleerd. Waarom heb ik hiervoor twee aparte kolommen? Nou, denk maar aan evenementen die eerst opnieuw werden gepland en later volledig werden geannuleerd. Dit gebeurt, en we hebben een manier om het op te nemen met deze kolommen.

    Afgezien van deze twee kolommen, werken alle overige kolommen hetzelfde als in de event tafel.

    Waarom twee evenementen koppelen door middel van parent_event_id ?

    Er zijn applicaties waarmee gebruikers alle toekomstige gevallen van een terugkerend evenement opnieuw kunnen plannen. In dergelijke gevallen hebben we twee opties. We kunnen alle toekomstige instanties opslaan in event_instance_exception (tip:geen acceptabele oplossing). Of we kunnen een nieuw evenement maken met nieuwe datum/tijd parameters in het event tabel en koppel deze met zijn eerdere gebeurtenis (de bovenliggende gebeurtenis) door middel van de id_parent_event kolom.

    Met deze oplossing kunnen we alle eerdere gebeurtenissen van een gebeurtenis ophalen, zelfs als het herhalingspatroon is gewijzigd.

    Hoe de afhandeling van terugkerende gebeurtenissen verbeteren?

    Er zijn een aantal complexere gebieden rond terugkerende evenementen die we niet hebben besproken. Hier zijn er twee:

    • Evenementen die plaatsvinden op feestdagen. Wanneer een bepaald geval van een gebeurtenis op een feestdag plaatsvindt, moet deze dan automatisch worden verplaatst naar de werkdag direct na de feestdag? Of moet het automatisch worden geannuleerd? In welke omstandigheden zou een van deze van toepassing zijn?
    • Conflicten tussen evenementen. Wat als bepaalde gebeurtenissen (die elkaar uitsluiten) op dezelfde dag vallen?

    Welke veranderingen moeten we doorvoeren om deze mogelijkheden in te bouwen? Vertel ons uw mening in het opmerkingengedeelte.


  1. PostgreSQL-lef:wat is "resjunk"?

  2. Apache Spark ODBC-stuurprogramma

  3. Unitils en DBMaintainer - hoe kan ik ze laten werken met meerdere gebruikers/schema's?

  4. Is er een manier om ARRAY's te gebruiken in Entity Framework + PostgreSql?