Entità annidate e calcolo sulla proprietà dell'entità foglia - Approccio SQL o NoSQL

10

Sto lavorando a un progetto per hobby chiamato Menu / Gestione ricette.

Ecco come sono le mie entità e le loro relazioni.

A Nutrient ha proprietà Code e Value

Un Ingredient ha una collezione di Nutrients

Un Recipe ha una collezione di Ingredients e occasionalmente può avere una collezione di altro recipes

A Meal ha una raccolta di Recipes e Ingredients

Un Menu ha una collezione di Meals

Le relazioni possono essere rappresentate come

In una delle pagine, per un menu selezionato ho bisogno di visualizzare le informazioni sui nutrienti efficaci calcolate in base ai suoi componenti (Pasti, Ricette, Ingredienti e nutrienti corrispondenti).

A partire da ora sto utilizzando SQL Server per archiviare i dati e sto navigando la catena dal mio codice C #, partendo da ogni pasto del menu e quindi aggregando i valori dei nutrienti.

Penso che questo non sia un modo efficace poiché questo calcolo viene eseguito ogni volta che viene richiesta la pagina e i componenti cambiano occasionalmente.

Stavo pensando di avere un servizio in background che mantiene una tabella denominata MenuNutrients ( {MenuId, NutrientId, Value} ) e popolerà / aggiornerà questa tabella con i nutrienti efficaci quando uno qualsiasi dei componenti (Pasto, Ricetta, Ingrediente) cambia.

Ritengo che un GraphDB sia adatto per questo requisito, ma la mia esposizione a NoSQL è limitata.

Voglio sapere quali sono le soluzioni / approcci alternativi a questo requisito di visualizzazione dei nutrienti di un determinato menu.

Spero che la mia descrizione dello scenario sia chiara.

    
posta Chandu 04.10.2013 - 02:30
fonte

7 risposte

8

In base ai requisiti e all'architettura, potrebbero esserci opzioni di miglioramento delle prestazioni:

  • Puoi utilizzare visualizzazioni indicizzate (matrializzate) Per migliorare leggi prestazioni sul livello RDBMS (server Sql). Fondamentalmente, tutto te è necessario:
    Creare una vista normale.
    Creare un indice cluster su quella vista .

  • L'utilizzo di un meccanismo di incassi a livello di applicazione migliorerà prestazioni.
    Se è possibile e fattibile usare incassare, avere una strategia di cassa come singleton lazy incassare ti aiuterà.

NoSQL:
Ci sono molti buoni articoli su Sql vs NoSql, come questo e questo

Le parti mi interessano:

Dove usare NoSql:

If your DB is 3NF and you don’t do any joins (you’re just selecting a bunch of tables and putting all the objects together, AKA what most people do in a web app.

Se utilizzato, tieni pronto per:

  • You end up writing jobs to do things like joining data from different tables/collections, something that an RDBMS would do for you automatically.
  • Your query capabilities with NoSQL are drastically crippled. MongoDb may be the closest thing to SQL but it is still extremely far behind. Trust me. SQL queries are super intuitive, flexible and powerful. NoSql queries are not.
  • MongoDb queries can retrieve data from only one collection and take advantage of only one index. And MongoDb is probably one of the most flexible NoSQL databases. In many scenarios, this means more round-trips to the server to find related records. And then you start de-normalizing data - which means background jobs.
  • The fact that it is not a relational database means that you won't have (thought by some to be bad performing) foreign key constrains to ensure that your data is consistent. I assure you this is eventually is going to create data inconsistencies in your database. Be prepared. Most likely you will start writing processes or checks to keep your database consistent, which will probably not perform better than letting the RDBMS do it for you.
  • Forget about mature frameworks like hibernate.

Oltre a decidere di utilizzare o meno NoSql, un utile articolo su Confronto DBMS NOSQL e il la loro intenzione potrebbe essere trovata qui come alcuni di essi sono focalizzati su letture alte, scritture basse, riduzioni di mappe, HA ...
Date un'occhiata alla classifica e alla popolarità di essi , per categoria potrebbe essere utile.

    
risposta data 08.10.2013 - 07:33
fonte
2

Dipende molto da come lo fai per ottenere i menu e le sostanze nutritive inizialmente. Perché pensi che non sarà efficiente?

Da quanto ho capito, vai al DB, prendi il menu, poi vai di nuovo, prendi ogni ricetta, poi vai di nuovo e prendi ogni ingrediente e così via. Questo è davvero inefficiente, poiché ci sono un sacco di domande e round trip sul server, che è la principale fonte di ritardi. Questo è noto come il problema SELECT N + 1.

Quello che dovresti fare è recuperare tutti i dati in una singola query, usando JOIN s per tutte le tabelle dal menu fino ai nutrienti, in modo che il server DB possa usare tutte le relazioni e gli indici per ottenere i dati tutto in una volta. L'app client C # elabora e visualizza solo il risultato finale. Fare così è molto più efficiente di andare uno alla volta.

In generale, utilizzando tecniche di query appropriate e gli indici giusti per le query critiche, i database relazionali possono essere eseguiti molto bene su tabelle di grandi dimensioni sotto carico.

    
risposta data 04.10.2013 - 03:35
fonte
2

Di fatto non hai bisogno di usare un db grafico, basta memorizzare i valori richiesti in un livello superiore. È come memorizzare un Order e OrderItems . non è necessario calcolare il totale ogni volta che un ordine sta per essere visualizzato. Calcola invece somme, IVA e altre cose e memorizzale con Order .

order.Subtotal = order.Items.Sum(item => item.Price);
order.Tax = order.Subtotal * 0.25m; // just a value
order.Total = order.Subtotal + order.Tax;

// fast forward time
var subTotal = order.Items.Sum(item => item.Price);
var tax = subTotal * 0.25m;
var total = subTotal + tax;

if (toal == order.Total) {
   Console.Log("Why the hell I've just re-calculated total?");
}
    
risposta data 09.10.2013 - 10:53
fonte
2

Sembra che tu abbia passato un po 'di tempo a pensare a come modellare meglio i dati in modo che possano essere facilmente aggiornati e interrogati. Tuttavia, ora sei nel punto in cui devi fornire l'accesso ai dati. Queste due cose sono preoccupazioni separate.

Hai detto di ricaricare la pagina sta causando una nuova query al database. Si menziona inoltre che il database verrà aggiornato occasionalmente e quando si desidera che tali aggiornamenti vengano visualizzati nella pagina in modo tempestivo. Il tuo metodo migliore per ridurre il sovraccarico delle query non è quello di farlo. Se esegui ripetutamente le stesse query e ottieni gli stessi risultati, perché non li memorizzi per un po '? Dovresti essere in grado di implementare la memorizzazione nella cache upstream senza modificare il resto del progetto. Consiglierei di leggere su resto . Indipendentemente se si implementa il progetto in un rdbms o problemi nosql con prestazioni di questo tipo si gestiscono meglio riducendo il numero di volte che si deve andare al database. Supponi di avere 100 richieste per la stessa ricetta in 60 secondi. Se si memorizza nella cache per 60 secondi, si raggiunge il database solo una volta, con un miglioramento delle prestazioni pari a 100 volte. Per vedere lo stesso livello di miglioramento passando a nosql richiederà molto più lavoro.

I sistemi di tipo Nosql possono essere un'ottima soluzione quando si hanno enormi quantità di dati o requisiti di velocità di lettura o scrittura estremi. Tuttavia, le prestazioni extra hanno il costo di buttare via cose come l'integrità referenziale.

    
risposta data 10.10.2013 - 22:21
fonte
2

Suggerisco di esaminare il schema di Segregazione della Responsabilità delle query dei comandi .

Fondamentalmente invece di creare un singolo modello per leggere e scrivere puoi creare 2 modelli diversi. Uno ottimizzato per l'aggiornamento e l'altro ottimizzato per le query (leggi, rapporti, ...). I 2 modelli sono sincronizzati (di solito con coerenza finale) usando eventi di dominio (vedi DDD).

Ho iniziato a studiare questo modello alcuni mesi fa e ha davvero cambiato il mio modo di modellare il software. Non è facile perché è un grande cambiamento, specialmente se usato con altre tecniche come DDD e Event Sourcing. Ma ne vale la pena.

Ci sono molte risorse disponibili sulla rete, ricerca di CQRS e DDD (ed eventualmente Event Sourcing).

Questo modello può essere utilizzato su SQL e noSql.

Nel tuo caso puoi licenziare un evento ogni volta che i nutrienti vengono modificati per aggiornare il modello di lettura che viene ottimizzato per la lettura. Il modello letto può essere ad esempio una vista denormalizzata dei nutrienti del menu (perché non usare un db nosql per una lettura efficiente). Puoi avere più modelli di lettura in base alle query che devi eseguire.

Ci sono alcune implicazioni che utilizzano questo approccio, ma è molto scalabile ed estensibile.

    
risposta data 12.10.2013 - 21:13
fonte
1

Sembra che per l'esperimento o lo scopo della conoscenza tu voglia provare Graph-DB ma il tuo esempio è chiaramente un esempio di dati gerarchici in cui possiamo Drill-Down / Up attraverso un nodo. Non sono esperto in Graph / Neo DB, ma vedo che non c'è molta complessità nel modo in cui l'utente / è possibile richiedere dati da questo schema. Vedo che la scelta della progettazione del database / schema dipende molto da come e da quale tipo di dati verranno interrogati. Poiché utilizzi SQLSERVER "Gerarchia" D è l'opzione migliore dal mio punto di vista per mettere questi nodi come parte di Tree.

    
risposta data 09.10.2013 - 06:35
fonte
1

Il mio suggerimento è di pensare come una macchina e non come un essere umano. Può sembrare ripetitivo, ma ciò che le macchine sono brave a. Una cosa che devi chiederti è "devo recuperare ogni oggetto, comunque, da visualizzare sulla mia pagina?" Se sì, continua quello che stai facendo, rispetto al recupero dei dati, i cicli della CPU sono trascurabili quando si fa matematica semplice.

    
risposta data 12.10.2013 - 19:54
fonte

Leggi altre domande sui tag