Es posible que una aplicación necesite obtener un valor de los datos fuente almacenados en una base de datos. Calcular un nuevo valor puede requerir un uso significativo de recursos de CPU, especialmente en el caso de grandes conjuntos de datos o en casos donde debe revisarse múltiples documentos.
Si se solicita con frecuencia un valor calculado, puede ser más eficiente guardar ese valor en la base de datos con anticipación. Cuando la aplicación solicita datos, solo se requiere una operación de lectura.
Acerca de esta tarea
Si las lecturas son significativamente más comunes que las escrituras, el patrón calculado reduce la frecuencia del cálculo de datos. En lugar de calcular valores en cada lectura, la aplicación almacena el valor calculado y lo recalcula según sea necesario. La aplicación puede volver a calcular el valor con cada escritura que cambie los datos fuente del valor calculado, o como parte de una tarea periódica.
Nota
Con las actualizaciones periódicas, no se garantiza que el valor calculado devuelto sea exacto. Sin embargo, este enfoque puede valer la pena la mejora del rendimiento si la precisión exacta no es un requisito.
Pasos
En este ejemplo, una aplicación muestra información sobre los espectadores de películas y la ganancia. Los usuarios pueden buscar una película en particular y cuánto dinero ganó esa película.
Insertar datos de muestra
Crea el screenings colección:
db.screenings.insertMany( [ { theater: "Alger Cinema", location: "Lakeview, OR", movie_title: "Lost in the Shadows", movie_id: 1, num_viewers: 344, revenue: 3440 }, { theater: "City Cinema", location: "New York, NY", movie_title: "Lost in the Shadows", movie_id: 1, num_viewers: 1496, revenue: 22440 }, ] )
Insertar los datos calculados
Los usuarios suelen querer saber cuántas personas vieron cierta película y cuánto dinero recaudó esa película. En el esquema actual, para añadir num_viewers y revenue, debes realizar una lectura para teatros que proyectaron una película con el título "Lost in the Shadows" y sumar los valores de esos campos.
Para evitar realizar ese cálculo cada vez que se solicite la información, se pueden calcular los valores totales y almacenarlos en una colección movies junto con el propio registro de la película:
db.movies.insertOne( { _id: 1, title: "Lost in the Shadows", total_viewers: 1840, total_revenue: 25880 } )
Datos computados actualizados
Considere que se añade una nueva prueba de despistaje a la colección screenings:
db.screenings.insertOne( { theater: "Overland Park Cinema", location: "Boise, ID", movie_title: "Lost in the Shadows", movie_id: 1, num_viewers: 760, revenue: 7600 } )
Los datos calculados en la colección movies ya no reflejan los datos de screening actuales. La frecuencia con la que se actualizan los datos calculados depende de la aplicación:
En un entorno de escritura baja, el cálculo puede ocurrir junto con cualquier actualización de los datos de
screenings.En un entorno con escrituras más regulares, los cálculos pueden realizarse en intervalos definidos (por ejemplo, cada hora). Los datos fuente en
screeningsno se ven afectados por los guardados en la colecciónmovies, por lo que puedes ejecutar cálculos en cualquier momento.
Para actualizar los datos calculados con base en los datos de cribado, puedes ejecutar la siguiente agregación a intervalos regulares:
db.screenings.aggregate( [ { $group: { _id: "$movie_id", total_viewers: { $sum: "$num_viewers" }, total_revenue: { $sum: "$revenue" } } }, { $merge: { into: { db: "test", coll: "movies" }, on: "_id", whenMatched: "merge" } } ] )
Resultados
El patrón calculado reduce la carga de trabajo de la CPU y aumenta el rendimiento de la aplicación. Considera el patrón computacional cuando tu aplicación realice los mismos cálculos repetidamente y tenga una alta relación de lectura a escritura.