Archiviazione dei dati per semestre

1

Il problema è simile a questa domanda , ma non a un duplicato. Quello che sto cercando è una soluzione migliore di quella attuale.

Sto costruendo un'applicazione web per un dipartimento nella mia università e, a causa di come funziona il college, le cose devono essere archiviate ogni semestre. Per archivio, intendo contrassegnato come non "corrente" in modo che tutto ciò che si è verificato nei semestri precedenti sia fuori mano, ma accessibile tramite qualcosa come /projects/archive se necessario.

Al momento, ho una semplice colonna archiviata booleana per ogni tabella che deve essere archiviata (utenti, progetti, eventi, ecc.). Prima che inizi il nuovo semestre, eseguo uno script che capovolge lo switch per tutte le righe in cui archived = FALSE . Non è l'approccio peggiore.

Il problema è che quando vengono create sempre più tabelle, il mio senso di DRY inizia a formicolare, dicendo che una colonna archiviata per ogni tabella è ridicola . Lo script cresce (di una riga) per ogni tabella che necessita di una colonna archiviata.

Fortunatamente sto usando il framework Rails, quindi lo script di archivio ha il seguente aspetto:

User.where(role: [User.roles[:faculty], User.roles[:student]], archived: false).update_all(archived: true)
Course.where(archived: false).update_all(archived: true) 
Enrollment.where(archived: false).update_all(archived: true)
Project.where(archived: false).update_all(archived: true)
Event.where(archived: false).update_all(archived: true)

Occorrono solo pochi secondi (le tabelle sono piuttosto piccole) e devono essere eseguite solo 4 volte all'anno. Devo notare che non si tratta di dati di classe enterprise con i quali ho a che fare. La tabella più grande è iscrizione che ha solo circa 5000 righe aggiunte per semestre (ovvero ~ 125.000 righe dopo 10 anni).

È una soluzione accettabile, o ce n'è una migliore? Se, ad esempio, si trattasse di dati a livello di Facebook con cui avevo a che fare, l'approccio dovrebbe essere diverso?

    
posta Chris Cirefice 11.04.2016 - 00:00
fonte

3 risposte

1

Questa soluzione è certamente una soluzione accettabile, considerando i vincoli e le dimensioni relativamente ridotte del database dopo 10 anni.

Tuttavia, la frequenza dell'archiviazione mostra che i dati sono intrinsecamente dipendenti dal tempo. Metterei davvero l'anno e il semestre o la data di validità parte dei dati. Ciò eviterebbe la necessità di archiviare e archiviare i duplicati (cioè diversi dati con archived:true e gli stessi valori, come ad esempio uno studente fallisce in un semestre e segue lo stesso corso nel prossimo semestre).

Se paragoni a facebook: facebook gestisce perfettamente una linea temporale, e solo i dati identificativi principali come nome, data di nascita, ecc. non dipendono dal tempo.

    
risposta data 11.04.2016 - 00:19
fonte
1

Un altro approccio potrebbe essere quello di avere una tabella Semesters . Le tue tabelle principali che sono ora in uso prenderebbero un semesterid come chiave esterna. Metti il bit attivo nella tabella Semesters (o interrogalo per confronto data / ora, ma probabilmente andrei con il bit di archivio).

Da lì, gestisci solo il bit dell'archivio Semesters e:

  1. Inner Unisciti a "semester attivi" nelle tue query principali o ...
  2. Crea alcune viste di base per rappresentare le attuali tabelle principali, che sono esse stesse interne al semestre attivo.

Il punto due sopra fornisce un po 'di livello di astrazione, quindi nella tua app / repository, lavori con le viste e senti come stai lavorando con i dati attivi. La gestione è abbastanza semplice in tutto.

(dopotutto, la naturale normalizzazione dei dati dovrebbe ricadere su un'entità di Semester, e se non si relaziona lì, probabilmente non ha bisogno di essere identificata come archiviata / attiva o no ... Ho adottato questo approccio in molte forme nel corso degli anni e ho trovato che funziona molto bene)

    
risposta data 11.04.2016 - 00:37
fonte
1

Abbiamo avuto un problema simile con milioni di righe al giorno. Darò un esempio con una sola tabella e può essere fatto in modo simile per gli altri.

Dì che il tavolo era ordini. gli ordini avrebbero i dati per la tabella corrente. Era sempre archiviato il sabato e i dati venivano spostati su un tavolo settimanale ad esempio, orders_20160409 avrebbe dati di ordini per la settimana del 9 aprile 2016. Una voce è stata fatta in order_map

order_map

data nome_tabella nome_server nome_database

20160409 orders_20160409 server1 db1

Se i dati erano grandi, a volte il processo in modo intelligente dividerebbe anche i dati e li inserirà in due tabelle diverse basate su determinate regole e creerà più voci. per esempio

data nome_tabella nome_server nome_database

20160409 orders_20160409 server1 db1

20160409 orders_20160409_1 server2 db2

Nel nostro database, a volte c'erano circa 100 voci per una singola tabella a causa del volume di dati.

Non abbiamo mai interrogato direttamente il database. Abbiamo utilizzato un'API che accetta il nome del tavolo (ordini) e la data settimanale (20160409).

Internamente questa funzione di query andrebbe alla tabella order_map, troverà i server, il database e il nome della tabella e genererà le query in parallelo.

In questo modo il front-end non aveva idea di cosa fosse fatto sul back-end e i dati potevano essere ristrutturati sul backend se necessario (a volte i dati venivano trasferiti da un server ad un altro server da dba a causa di problemi di prestazioni).

L'unica cosa che devi fare è scrivere e programmare uno script automatico che viene eseguito ogni fine settimana / semestre e archivia i dati. Oh, naturalmente, esegui una query tramite un'API (magari un servizio web) dopo aver creato l'API.

Potrebbe trattarsi di un intervento eccessivo, ma solo per farti conoscere un approccio per enormi volumi di dati.

    
risposta data 11.04.2016 - 03:52
fonte

Leggi altre domande sui tag