2009-06-14 8 views
11

Uno dei vantaggi del supporto dei database relazionali sono le funzioni di aggregazione come count, sum, avg ecc. Ma sembra che se si sta utilizzando GAE, quando si inserisce o si aggiorna un record è necessario calcolare e memorizzare il conteggio, somma, avg, ecc. valori dell'intera tabella. Ma cosa succede se hai molti raggruppamenti condizionali? Data una Persona:C'è un modo per fare funzioni di aggregazione su Google App Engine?

class Person { 
    @Id 
    Integer age; 
    String city; 
} 

Se voglio

  1. il numero totale delle persone e
  2. l'età media

È vero che ogni volta che creo, aggiornare o cancellare una persona dovrei anche calcolare entrambi gli aggregati e memorizzarli come colonne separate nella stessa tabella. Se voglio anche i valori totali e medi per città, dovrei memorizzare questi valori per ogni città anche come colonne separate nella stessa tabella?

risposta

6

Destra: per utilizzare correttamente lo spazio di archiviazione GAE, è necessario de-normalizzare in modo selettivo alcuni aspetti del modello, mantenendo i dati "ridondanti" che, in un DB in forma normale, si riaggancia al volo, ad esempio gli aggregati (nel complesso e "raggruppati per" quelli).

Tuttavia, non aggiungere tali campi alla tabella Person nel tuo caso - non ha molto senso! Crea un'altra tabella PersonAggregates con colonne come Città (null/mancante per totali complessivi), Conta, TotalAges (più semplice da mantenere: calcola la media in qualsiasi momento come totale diviso per conteggio).

+0

Questo sembra incredibilmente costoso, sia nei tempi di sviluppo del software che nelle spese della CPU. Devo pensare che Google si avvicini al datastore in questo modo per una buona ragione, ma la mia reazione iniziale è di orrore. Alex, qual è il miglior libro o documento di buone pratiche a cui faresti riferimento ragazzi come me? –

+0

Ottima domanda, e sono felice di vedere che ho scelto un buon approache creando un tipo solo per l'aggregazione. Tuttavia, come dice @JD, l'installazione di questa aggregazione può essere costosa e soggetta a errori. Non ho trovato una proprietà per questo (qualcosa come 'totalAge = db.AggregateProperty (of = Person.age)'. Quale pensi che sia l'approccio migliore? – rds

+0

Ho appena trovato http://code.google.com/ appengine/articoli/sharding_counters.html – rds

3

Per gli aggregati di uso frequente è consigliabile aggiornarli su ogni aggiornamento/inserimento/eliminazione.

Se non è stato progettato tali aggregati nella vostra applicazione fin dall'inizio, è possibile eseguire uno script tramite Remote DataStore API o impostare un server-side cron job che elaborerà tutte le entità e calcolare gli aggregati. È abbastanza facile, basta tenere a mente la quota della CPU per richiesta.