2013-08-02 10 views
6

Sto cercando un modo efficiente di memorizzare insiemi di oggetti che si sono verificati insieme durante gli eventi, in modo tale da poter generare statistiche aggregate su di essi giorno per giorno.Come memorizzare set di oggetti che si sono verificati insieme durante gli eventi?

Per fare un esempio, immaginiamo un sistema che tenga traccia delle riunioni in un ufficio. Per ogni riunione registriamo per quanti minuti è stato e in quale stanza si è svolto.

Voglio ottenere statistiche suddivise sia per persona che per stanza. Non ho bisogno di tenere traccia delle singole riunioni (quindi no meeting_id o qualcosa di simile), tutto quello che voglio sapere sono le informazioni aggregate giornaliere. Nella mia applicazione reale ci sono centinaia di migliaia di eventi al giorno, quindi non è possibile memorizzarli singolarmente.

mi piacerebbe essere in grado di rispondere a domande come:

Nel 2012, quanti minuti hanno Bob, Sam, e Julie trascorrono in ogni sala conferenze (non necessariamente insieme)?

probabilmente bene a che fare questo con 3 domande:

>>> query(dates=2012, people=[Bob]) 
{Board-Room: 35, Auditorium: 279} 
>>> query(dates=2012, people=[Sam]) 
{Board-Room: 790, Auditorium: 277, Broom-Closet: 71} 
>>> query(dates=2012, people=[Julie]) 
{Board-Room: 190, Broom-Closet: 55} 

Nel 2012, quanti minuti hanno Sam e Julie trascorrono incontrarsi in ogni sala conferenze? Che mi dici di Bob, Sam e Julie tutti insieme?

>>> query(dates=2012, people=[Sam, Julie]) 
{Board-Room: 128, Broom-Closet: 55} 
>>> query(dates=2012, people=[Bob, Sam, Julie]) 
{Board-Room: 22} 

Nel 2012, quanti minuti ha fatto ogni persona spende nel Board-Room?

>>> query(dates=2012, rooms=[Board-Room]) 
{Bob: 35, Sam: 790, Julie: 190} 

Nel 2012, quanti minuti è stato il Board-camera in uso?

Questo è in realtà piuttosto difficile poiché la strategia ingenua di sommare il numero di minuti che ogni persona impiega si tradurrà in un eccessivo conteggio. Ma probabilmente possiamo risolvere questo problema memorizzando il numero separatamente come meta-persona Chiunque:

>>> query(dates=2012, rooms=[Board-Room], people=[Anyone]) 
865 

Quali sono alcune buone strutture di dati o banche dati che posso utilizzare per abilitare questo tipo di interrogazione? Dal momento che il resto della mia applicazione utilizza MySQL, sono tentato di definire una colonna stringa che contiene i (ordinate) ID di ogni persona nel corso della riunione, ma la dimensione di questo tavolo crescerà abbastanza rapidamente:

2012-01-01 | "Bob"   | "Board-Room" | 2 
2012-01-01 | "Julie"   | "Board-Room" | 4 
2012-01-01 | "Sam"   | "Board-Room" | 6 

2012-01-01 | "Bob,Julie"  | "Board-Room" | 2 
2012-01-01 | "Bob,Sam"  | "Board-Room" | 2 
2012-01-01 | "Julie,Sam"  | "Board-Room" | 3 

2012-01-01 | "Bob,Julie,Sam" | "Board-Room" | 2 

2012-01-01 | "Anyone"  | "Board-Room" | 7 

Cos'altro posso fare?

+1

Quindi, per chiarire, avete un "incontro" di bajillion in corso, quindi li aggregate di giorno. Ciò significa che hai passato dei minuti per il giorno di intersezione delle persone in intersezione delle sale (chiamiamolo R U P U D). Vuoi R U (intersezione P1 intersezione P2 P3) U D in un modo in cui non devi memorizzare ogni riunione ... – Temuz

+0

Sì esattamente! Se memorizzassimo meeting_ids, potremmo semplicemente prendere gli UNIQUE meeting_ids e quindi cercare informazioni per ognuno, ma sarebbe una tonnellata di record per MySQL da aggregare. –

+0

Questi set di query sono stati risolti o possono essere modificati? Voglio dire, può essere come trovare tutte le volte in cui Julia e Bob non erano in questa stanza di incontro con Borad. Penso che Meeting Id non sia così importante qui, poiché possiamo ottenere incontri unici usando la combinazione di tempo e BoardRoom. – AKS

risposta

0

La tua domanda è poco chiara perché dici di non voler archiviare ogni singola riunione, ma come si ottengono le statistiche correnti della riunione (date)? Inoltre ogni tabella data gli indici giusti può essere molto veloce anche con un sacco di record.

Dovresti essere in grado di utilizzare una tabella come log_meeting.Immagino che potrebbe contenere qualcosa come:

employee_id, room_id, date (as timestamp), time_in_meeting 

Dove chiavi esterne per dipendente id al tavolo dei dipendenti, e la chiave di id stanza a stanza tabella

Se indice dipendente id, sala id, e la data si dovrebbe avere una ricerca piuttosto rapida mentre gli indici mysql a più colonne vanno da sinistra a destra in modo tale da ottenere un indice (ID dipendente, ID dipendente + ID stanza e ID dipendente + ID stanza + data e ora) durante le ricerche. Questo è spiegato più nella parte multi-indice:

http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

0

Rifiutando di memorizzare incontri (e gli oggetti correlati) singolarmente, si stanno perdendo la fonte originale di informazioni.

Non sarà possibile compensare questa perdita di dati, a meno che non si memorizzi regolarmente l'elenco completo di tutti i potenziali aggregati giornalieri (o mensili o settimanali o ...) che potrebbero essere necessari per una domanda successiva. !

credetemi, sarà un incubo ...

0

Se il numero di persone che sono costanti e non molto grande quindi è possibile assegnare una colonna per ciascuna persona presente o meno e conservare la camera, data e il tempo in altre 3 colonne questo può rimuovere i problemi di divisione delle stringhe.

Anche per la natura della tua domanda, prima di tutto sento che è necessario assegnare Ids a tutte le stanze, persone, ecc. Non c'è bisogno di una stringa lunga ripetitiva nel DB. Prova anche a ridurre qualsiasi operazione di stringa e lavora usando i singoli dati in ogni colonna per ottenere prestazioni di intersezione migliori. Inoltre è possibile memorizzare una permutazione di tutte le persone in una tabella e assegnare un id per loro quindi utilizzare uno di quegli id ​​nella tabella di data e ora effettiva. Ma tutte le tecniche richiedono che qualcosa sia costante nelle persone o nelle stanze.

0

Non capisco se si conoscono tutte le "domande" in fase di progettazione o è possibile aggiungerne di nuove durante lo sviluppo/tempo di produzione - questo approccio richiederebbe di mantenere tutti i dati tutto il tempo.

Bene, se si conoscono tutte le vostre domande, sembra il classico "sistema bancario" che ricalcola i dati su base giornaliera.

Come ci penso.

  1. Sembra come si hanno limitato il numero di camere, persone, giorni ecc
  2. Raccogliere dati di registrazione su base giornaliera, una tabella per ogni giorno. Solo un evento, una riga di database, tutte le informazioni (campo) di cui hai bisogno.
  3. Inizia ad analizzare i dati utilizzando uno script di crone a "mezzanotte".
  4. Aggiorna statistiche per persone, stanze, ecc. Aumenta solo il numero di ore trascorse da Bob nella sala xyz ecc. Tutto ciò di cui hai bisogno.
  5. Come analizzato i dati sono limitati e relativamente piccole, come si analizzati (impacco) li, il sistema possono contenere anche varie query come indici sarebbero relativamente piccola ecc

si potrebbe essere in grado di utilizzare carta scalabile/ridurre algoritmo.

0

Non è possibile evitare di archiviare i fatti atomici come segue: (la sala riunioni, le persone, la durata, il giorno), che è probabilmente solo un consolidamento debole quando le stesse persone si incontrano più volte nella stessa stanza in lo stesso giorno.Forse questo succede molto nel tuo ufficio :).

Rendere comparabili i gruppi è un problema interessante, ma se si compongono sempre le stringhe membro, è possibile farlo con confronti tra stringhe. Questo non è "normale" comunque. Per normalizzare avrai bisogno di una tabella delle relazioni (da molti a molti) e componi una tabella temporanea dal tuo set di query in modo che si unisca rapidamente, o usi una clausola "IN" e un conteggio aggregato per assicurarti che tutti siano presenti (vedrai cosa intendo quando lo provi).

Penso che sia possibile ricavare i minuti in cui era in uso la sala riunioni poiché le riunioni non dovrebbero sovrapporsi, quindi una somma funzionerà.

Per l'efficienza di archiviazione, utilizzare le chiavi integer per tutto con le tabelle di ricerca. Dereferenzia gli interi durante l'analisi della query, o usa solo buoni vecchi join se ti senti tradizionale.

Ecco come lo farei comunque :).