Concetto per gestire appuntamenti ricorrenti

6

La nostra azienda ha implementato un sistema di calendario alcuni mesi fa con appuntamenti ricorrenti, utilizzando le stringhe iCal per memorizzare i criteri di appuntamento ricorrenti.

Stiamo iniziando a riscontrare problemi di prestazioni a causa di questi.

Il nostro pensiero attuale è qualcosa di simile ...

Un utente richiede tutti gli appuntamenti per un intervallo di date. In genere non più di 30 giorni.
Prendiamo tutti gli eventi non ricorrenti dal database che rientrano in questo intervallo di date. Quindi prendiamo TUTTI gli eventi che contengono una stringa iCal e li eseguiamo attraverso un processore per determinare se l'evento si ripete nel nostro intervallo di date richiesto. Ad esempio, l'utente potrebbe avere l'evento che inizia l'1/1/14, che si ripete ogni martedì e mercoledì in corso per sempre. Un altro evento, tuttavia, può iniziare l'1/1/14, ripetendo ogni martedì e mercoledì per un mese ed è ora al di fuori della nostra gamma selezionata. Il primo si ripeterà al nostro intervallo di date e sarà incluso. Il secondo non lo farebbe.

Per quanto posso dire, non c'è davvero un buon modo per determinare alcun tipo di filtro in modo da non dover estrarre ognuno di questi eventi dal database e testarli per vedere se corrispondono il nostro intervallo di date.

Man mano che il numero di eventi ricorrenti aumenta, il nostro database viene rallentato con richieste che restituiscono sempre più record e il nostro server deve elaborare ognuno di questi, molti dei quali non sono necessari, ma non sappiamo fino a quando non li raggiungiamo sul server e li elaboriamo.

Qualcuno l'ha già affrontato prima, e c'è un algoritmo migliore che possiamo implementare per limitare il numero di record restituiti?

    
posta Scottie 16.12.2014 - 18:45
fonte

4 risposte

4

Mi sembra che il tuo problema sia nella tua prima frase:

Our company implemented a calendar system a few months back with recurring appointments, using iCal strings to store the recurring appointment criteria.

La scansione di tutti i record per determinare gli intervalli di date non è semplicemente scalabile. In sostanza, stai usando il tuo database come un file flat, quindi ovviamente è lento.

Invece di memorizzare le stringhe iCal non elaborate, interpreta le stringhe prima che le hai inserite nel database in modo da poter eseguire query come

select * from records 
where startdate < "2014-01-30 00:00:00" and enddate > "2014-01-01 00:00:00";

Se hai davvero bisogno della stringa iCal, puoi lasciarla anche nel DB, ma cose come le date di inizio / fine dell'appuntamento dovrebbero essere colonne DB in modo da poterle cercare in modo efficiente.

    
risposta data 16.12.2014 - 18:59
fonte
4

In uno dei libri di Tom Kyte ha descritto una società con questo problema esatto. Hanno fatto quello che hai fatto e la performance è stata terribile. La sua raccomandazione era di memorizzare ogni istanza di un appuntamento ricorrente nel database fino ad un certo punto in futuro. Questo ha risolto tutti i loro problemi di prestazioni con le ricerche degli appuntamenti.

Sì, potrebbero esserci centinaia di occorrenze di alcuni appuntamenti. E allora? Hai solo bisogno di memorizzare gli orari di inizio, e questo è solo alcuni kilobyte. E non è necessario archiviarli nel futuro indefinito. Due o tre anni sono molti. Quando è l'ultima volta che hai voluto sapere quali appuntamenti hai avuto in una data del 2017?

    
risposta data 16.12.2014 - 23:33
fonte
0

Vorrei offrirti la mia soluzione per questo riconoscendo che:

  1. Tutti gli appuntamenti, singoli o ricorrenti, hanno almeno una data
  2. In base a impostazioni ragionevoli, gli appuntamenti che ricorrono spesso hanno uno schema

Nella mia soluzione, per ogni appuntamento avrai una data di inizio e una data di fine. Nel caso di un singolo appuntamento, è possibile lasciare la data di fine uguale alla data di inizio. Nel caso di un nuovo appuntamento in futuro, puoi lasciare la data di fine come vuota o qualsiasi valore nel futuro.

Ora per tutti gli appuntamenti, hai una colonna aggiuntiva chiamata: tipo e modello. In questa colonna, puoi avere un tipo di enum che specifica il modello di ripetizione come giornaliero, settimanale, mensile, bisettimanale. Per gli appuntamenti che non si ripetono, il tipo può essere una tantum.

Questo riguarda anche il caso in cui un appuntamento è effettivamente parte di uno nuovo, ma è stato ri-programmato per essere fuori schema. Puoi impostare il tipo di esso in qualcosa come re-schedule può possedere una colonna di riferimento aggiuntiva per fare riferimento all'appuntamento ricorrente originale.

Ora, quando desideri cercare tutti gli appuntamenti (di qualsiasi tipo) che corrispondono al tuo intervallo di date, puoi utilizzare la data di inizio e di fine insieme alla colonna "tipo e modello". Un esempio specifico per il caso di ricerca di appuntamenti nell'intervallo dal 1 ° ottobre 2014 al 1 ° dicembre 2014 è il seguente:

select * from APP as A where
    ((A.sd >= $start AND A.sd <= $end) OR (A.ed <= $end AND A.ed >= $start) OR (A.sd <= $start AND A.ed >= $end) ) 
    AND (A.type = 'Single' OR A.type = 'ReSchedule' OR inRange($start, $end, A.sd, A.type) )

Qui devi costruire la tua funzione per inRange() , la semantica prende la variabile $end come un intero, meno il numero intero per A.sd e la divisione per l'intervallo di pattern. Quindi controlli se $end meno la mod della divisione è maggiore o uguale a $start

InRange() rallenterà la tua query esaminando tutte le corrispondenze non elaborate. Ma questo sarà molto meglio del tuo concetto di design originale. Puoi implementare InRange() utilizzando PL / SQL o scrivere un metodo esterno utilizzando i risultati della query SQL per filtrare correttamente le corrispondenze non elaborate.

    
risposta data 17.12.2014 - 01:01
fonte
0

Per come la vedo io, il database dovrebbe memorizzare solo un tipo di appuntamento. Le informazioni sull'appuntamento devono contenere (tra l'altro) la data di inizio, il modello di ripetizione e la data di fine.

Il db non dovrebbe avere un appuntamento per ogni "ricorrente", solo quello iniziale e il suo schema di ripetizione. L'applicazione dall'altra parte estrae gli appuntamenti pertinenti e calcola quelli "ricorrenti" in base al modello. Ciò significa, ovviamente, che se una persona desidera tutti gli appuntamenti che si verificheranno nei prossimi 30 giorni, recupererà tutti i record con una data di inizio inferiore a ora + 30 giorni e una data di fine maggiore di adesso.

Se davvero volevi che il db lo gestisse, forse il db potrebbe essere fatto per fare questi calcoli e restituire una tabella temporanea con questi appuntamenti extra.

Infine, quando arriva il momento di creare / aggiornare un appuntamento, la data di fine (se desiderata) deve essere popolata con la data di fine calcolata (impostata esplicitamente dal client o calcolata implicitamente dalla funzione client o database , nel caso in cui il pattern specifichi un numero di occorrenze o altri criteri pre-calcolabili).

    
risposta data 07.12.2016 - 21:54
fonte

Leggi altre domande sui tag