Estoy trabajando en un proyecto de pasatiempo llamado Gestión de menús / recetas.
Así es como se ven mis entidades y sus relaciones.
A Nutrient
tiene propiedades Code
yValue
An Ingredient
tiene una colección deNutrients
A Recipe
tiene una Colección de Ingredients
y ocasionalmente puede tener una colección de otrosrecipes
A Meal
tiene una colección de Recipes
yIngredients
A Menu
tiene una colección deMeals
Las relaciones se pueden representar como
En una de las páginas, para un menú seleccionado, necesito mostrar la información de nutrientes efectivos calculada en función de sus componentes (comidas, recetas, ingredientes y los nutrientes correspondientes).
A partir de ahora estoy usando SQL Server para almacenar los datos y estoy navegando por la cadena desde mi código C #, comenzando desde cada comida del menú y luego agregando los valores de nutrientes.
Creo que esta no es una forma eficiente, ya que este cálculo se realiza cada vez que se solicita la página y los componentes cambian ocasionalmente.
Estaba pensando en tener un servicio en segundo plano que mantenga una tabla llamada MenuNutrients ( {MenuId, NutrientId, Value}
) y que llene / actualice esta tabla con los nutrientes efectivos cuando cambie cualquiera de los componentes (Comida, Receta, Ingrediente).
Siento que un GraphDB sería una buena opción para este requisito, pero mi exposición a NoSQL es limitada.
Quiero saber cuáles son las soluciones / enfoques alternativos para este requisito de mostrar los nutrientes de un menú determinado.
Espero que mi descripción del escenario sea clara.
fuente
Respuestas:
Según los requisitos y la arquitectura, puede haber opciones de mejora del rendimiento:
Puede usar vistas indexadas (matrializadas) para mejorar el rendimiento de lectura en el nivel RDBMS (servidor SQL).
Básicamente, todo lo que necesita hacer es:
Crear una vista regular.
Cree un índice agrupado en esa vista .
El uso de un mecanismo de cobro en el nivel de aplicación mejorará el rendimiento.
Si es posible y factible usar el cobro, tener una estrategia de efectivo como el cobro simple de perezoso lo ayudará.
NoSQL:
Hay un montón de buenos artículos sobre SQL vs NoSQL, como este y este
Los intereses de piezas de mí:
Donde utilizar NoSQL:
Cuando lo use, esté listo para:
Además de decidir usar o no usar NoSql, se puede encontrar un artículo útil sobre Comparación de DBMS NOSQL y la intención de ellos aquí, ya que algunos de ellos se centran en lecturas altas, escrituras bajas, reducción de mapas, HA ...
Echar un vistazo En la clasificación y popularidad de ellos , por categoría puede ser útil.
fuente
De hecho, no necesita usar un gráfico db, solo almacene los valores requeridos en un nivel superior. Es como almacenar un
Order
yOrderItems
. no tiene que calcular el total cada vez que se va a mostrar un pedido. En cambio, solo calcula la suma, el iva y otras cosas y las almacena con suOrder
.fuente
Sugiero mirar el patrón de segregación de responsabilidad de consulta de comando .
Básicamente, en lugar de crear un solo modelo para leer y escribir, puede crear 2 modelos diferentes. Uno optimizado para actualizar y el otro optimizado para consultas (lectura, informes, ...). Los 2 modelos están sincronizados (generalmente con una coherencia eventual) utilizando eventos de dominio (ver DDD).
Empecé a estudiar este patrón hace unos meses y realmente cambió mi forma de modelar software. No es fácil porque es un gran cambio, especialmente cuando se usa con otras técnicas como DDD y Event Sourcing. Pero vale la pena.
Hay muchos recursos disponibles en la red, busque CQRS y DDD (y eventualmente Event Sourcing).
Este patrón se puede usar tanto en SQL como en noSql.
En su caso, puede activar un evento cada vez que se cambian los nutrientes para actualizar el modelo de lectura que está optimizado para la lectura. El modelo de lectura puede ser, por ejemplo, una vista desnormalizada de los nutrientes del menú (¿por qué no usar un nosql db para una lectura eficiente)? Puede tener múltiples modelos de lectura basados en las consultas que necesita realizar.
Hay algunas implicaciones al usar este enfoque, pero es muy escalable y extensible.
fuente
Depende en gran medida de cómo hacer para obtener los menús y los nutrientes inicialmente. ¿Por qué crees que no será eficiente?
Por lo que entiendo, vas al DB, obtienes el menú, luego vuelves, obtienes cada receta, luego vuelves y obtienes cada ingrediente y así sucesivamente. Esto es realmente ineficiente, ya que hay muchas consultas y viajes de ida y vuelta al servidor, que es la principal fuente de demoras. Esto se conoce como el problema SELECT N + 1.
Lo que debe hacer es obtener todos los datos en una sola consulta, utilizando
JOIN
s para todas las tablas desde el menú hasta los nutrientes, para que el servidor de base de datos pueda usar todas las relaciones e índices para obtener los datos de una vez. La aplicación cliente C # solo procesa y muestra el resultado final. Hacerlo es mucho más eficiente que ir uno por uno.En general, utilizando técnicas de consulta adecuadas y los índices correctos para consultas críticas, las bases de datos relacionales pueden funcionar muy bien en tablas grandes bajo carga.
fuente
JOIN
s que no deberían ser una carga para el servidor (a menos que estemos hablando de buscar cientos o miles de filas), si la indexación es adecuada esta en su lugar. Incluso con grandes conjuntos de datos, siempre puede crear una vista de todo el resultado e incluso indexar la vista para tener el resultado precalculado, si el rendimiento se vuelve un problema.Parece que ha pasado algún tiempo pensando en la mejor forma de modelar los datos para que puedan actualizarse y consultarse fácilmente. Sin embargo, ahora está en el punto donde necesita proporcionar acceso a los datos. Esas dos cosas son preocupaciones separadas.
Usted menciona que la recarga de la página está causando una nueva consulta a la base de datos. También menciona que la base de datos se actualizará ocasionalmente y, cuando sea así, desea que esas actualizaciones se muestren en la página de manera oportuna. Su mejor método para reducir la sobrecarga de consultas es no hacerlas. Si ejecuta las mismas consultas una y otra vez y obtiene los mismos resultados, ¿por qué no las almacena en caché por un tiempo? Debería poder implementar algo de almacenamiento en caché en sentido ascendente sin modificar el resto del proyecto. Recomendaría leer sobre descanso. Independientemente de si implementa el proyecto en un rdbms o nosql, los problemas con el rendimiento de este tipo se manejan mejor reduciendo la cantidad de veces que tiene que ir a la base de datos. Digamos que tiene 100 solicitudes para la misma receta en 60 segundos. Si almacena en caché durante 60 segundos, solo golpea la base de datos una vez, por lo que es una mejora de 100 veces en el rendimiento. Ver ese mismo nivel de mejora al cambiar a nosql requerirá mucho más trabajo.
Los sistemas de tipo Nosql pueden ser una gran solución cuando tiene grandes cantidades de datos o requisitos de velocidad extrema de lectura o escritura. Sin embargo, ese rendimiento adicional tiene el costo de desechar cosas como la integridad referencial.
fuente
Parece que para el experimento o el propósito del conocimiento desea probar Graph-DB, pero su ejemplo es claramente un ejemplo de datos jerárquicos donde podemos profundizar / descender a través de un nodo. No soy experto en Graph / Neo DB pero puedo ver que no hay mucha complejidad en la forma en que el usuario / usted puede solicitar datos de este esquema. Veo que la elección del diseño de la base de datos / esquema depende mucho de cómo y qué tipo de datos se consultarán en su contra. Como usted usa SQLSERVER "HierarchyI" D es la mejor opción desde mi punto de vista para poner estos nodos como parte de Tree.
fuente
Mi sugerencia es pensar como una máquina y no como un humano. Puede parecer repetitivo, pero en eso son buenas las máquinas. Una cosa que debe preguntarse es "¿tengo que recuperar todos los objetos, de todos modos, para mostrarlos en mi página?" En caso afirmativo, continúe con lo que está haciendo, en comparación con la recuperación de datos, los ciclos de CPU son insignificantes cuando se realizan cálculos matemáticos simples.
fuente