modo efficace per modellare i dati aggregati di una relazione molti-a-uno (ad esempio Conteggio voti su una questione StackOverflow)

StackOverflow https://stackoverflow.com/questions/923352

Domanda

Sono curioso di sapere quale sia il modo migliore per modellare questo per ottimizzare le prestazioni ... non così preoccupato per l'integrità dei dati in tempo reale

continuerò con l'esempio StackOverflow

Question
  id
  title
Votes
  id
  user
  question

Una domanda ha molti voti

Per molte query tuttavia, siamo solo interessati con il numero complessivo dei voti (per esempio per mostrare accanto alla domanda).

teoria bene relazionale db creerebbe le due entità (Q e V) le relazioni distinte, che richiedono un join poi una somma o contare chiamata aggregata.

Un'altra possibilità è quella di rompere forma normale ed occasionalmente materializzare il valore complessivo di utili come attributo in questione (ad esempio Question.votes). La performance è guadagnato su legge, tuttavia, a seconda di come stantio siete disposti a lasciare i vostri "voti" Get Data, richiede molto di più diritti a detto record di domanda ... a loro volta ostacolano le prestazioni.

Altre tecniche che comportano la memorizzazione nella cache, ecc possono essere utilizzati. Ma mi chiedo solo, le prestazioni saggio qual è la soluzione migliore? Diciamo che il sito è più alto traffico e la ricezione di una notevole quantità di più voti di domande.

Apri per modelli non relazionali come bene.

È stato utile?

Soluzione

E 'improbabile che un join sarà troppo lento in questo caso, soprattutto se si dispone di un indice su (domanda) nella tabella Voti.

Se è davvero troppo lento, è possibile memorizzare nella cache il conteggio dei voti nella tabella Domanda:

 id - title - votecount

È possibile aggiornare il votecount ogni volta che si registra un voto. Ad esempio, da una stored procedure o direttamente dal codice dell'applicazione.

Gli aggiornamenti sono difficili, ma dal momento che non sei così preoccupata per coerenza, credo che sia ok se il voto è a volte non esattamente a destra. Per correggere eventuali errori, è possibile rigenerare periodicamente tutti i punti memorizzati nella cache del tipo:

 UPDATE q
 SET votecount = count(v.question)
 FROM questions q
 LEFT JOIN votes v on v.question = q.id

Il conteggio complessivo (v.question) restituisce 0 se nessuna domanda è stata trovata, in contrapposizione a contare (*), che sarebbe tornato 1.

Se serrature sono un problema, è consigliabile utilizzare "con (nolock)" o "livello impostato isolamento di transazione leggere non impegnati" per serrature bypass (di nuovo, sulla base di integrità dei dati essendo una bassa priorità.)

In alternativa al NOLOCK, considerare "leggere snapshot impegnato", che è significato per i database con lettura pesante e meno attività di scrittura. È possibile accenderlo con:

ALTER DATABASE YourDb SET READ_COMMITTED_SNAPSHOT ON;

E 'disponibile per SQL Server 2005 e versioni successive. Questo è come funziona Oracle di default, ed è ciò che utilizza StackOverflow stessa. C'è anche un Coding Horror blog su di esso.

Altri suggerimenti

Ho usato viste indicizzate da SQL 2005 in tutto il luogo per questo genere di cose su un sito di social networking. Il nostro carico è stato sicuramente un elevato rapporto di letture / scritture in modo ha funzionato bene per noi.

Vorrei suggerire mantenere il voto in memoria per la durata dell'applicazione. Perché colpire un DB per qualcosa di semplice come un conteggio, quando ad un certo punto si dovrà caricare la voce di una volta e ha chiesto che cosa l'importo iniziale era su richiesta. Essa ha anche molto a che fare con i repository come si sta di esecuzione, se la tua domanda oggetto carica i pigri voti, ma carichi desiderosi il conteggio dei voti, allora si può accelerare il processo pur non avendo un problema di tenere in memoria. Ancora mantenere i voti in db, basta mantenere il conteggio nell'applicazione

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top