2009-06-14 13 views
11

Una de las mejores cosas que las bases de datos relacionales soportan son las funciones agregadas como count, sum, avg, etc. Pero parece que si estás usando GAE, al insertar o actualizar un registro debes calcular y almacenar el conteo, suma, media, etc. valores de toda la tabla. Pero, ¿y si tienes muchas agrupaciones condicionales? Dada una persona:¿Hay alguna forma de agregar funciones en Google App Engine?

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

Si quiero

  1. el número total de personas y
  2. la edad media

¿Es cierto que cada vez que crear, actualizar o borrar una persona también debería calcular ambos agregados y almacenarlos como columnas separadas en la misma tabla. Si también quiero los valores totales y medios por ciudad, ¿debo guardar estos valores para cada ciudad también como columnas separadas en la misma tabla?

Respuesta

6

Derecha: para usar el almacenamiento GAE correctamente, debe desregularizar selectivamente algunos aspectos de su modelo, manteniendo los datos "redundantes" que, en un DB en forma normal, podría recalcular sobre la marcha, como los agregados (general y "agrupados por").

Sin embargo, no agregue tales campos a la tabla Person en su caso - ¡eso tiene poco sentido! Haga otra tabla PersonAggregates con columnas como City (nulo/faltante para totales generales), Count, TotalAges (más fácil de mantener: calcule el promedio en cualquier momento como total dividido por conteo).

+0

Esto suena increíblemente caro, tanto en tiempos de desarrollo de software como en cargas de CPU. Tengo que pensar que Google se acerca al almacén de datos de esta manera por una buena razón, pero mi reacción inicial es de horror. Alex, ¿cuál es un buen libro de buenas prácticas o un documento al que recomendarías tipos como SQL pesado? –

+0

Excelente pregunta, y me complace ver que elegí un buen enfoque creando un tipo solo para la agregación. Sin embargo, como dice @JD, implementar esta agregación puede ser costoso y propenso a errores. No he encontrado una propiedad para esto (algo así como 'totalAge = db.AggregateProperty (of = Person.age)'. ¿Cuál crees que es el mejor enfoque? – rds

+0

Acabo de encontrar http://code.google.com/ appengine/articles/sharding_counters.html – rds

3

Para agregados de uso frecuente lo mejor es actualizarlos en cada actualización/inserción/eliminación.

Si no está diseñada tales agregados en su aplicación desde el principio, puede ejecutar una secuencia de comandos a través de Remote DataStore API o configurar una del lado del servidor cron job que procesará todas las entidades y calcular los agregados. Es bastante fácil, solo tenga en cuenta la cuota de CPU por solicitud.