2013-03-08 16 views
8

Considerare un sito in cui le persone votano su (+1) o giù (-1) sul loro colore preferito e ho due tabelle:Qual è il metodo SELECT più efficiente e perché?

Un elenco di tutti i colori per cui le persone possono votare e la seconda tabella registra ogni singolo voto fatto, di che colore era e se era +1 o -1.

Per quanto riguarda il recupero voto complessivo per un colore specifico, sarebbe più efficiente includono un punteggio complessivo sul tavolo i colori e quando una persona vota c'è una dichiarazione di inserimento e un'istruzione di aggiornamento:

INSERT INTO votes (colour,vote) VALUES (red,-1); 
UPDATE colours SET score=score-1 WHERE colour='red'; 

SELECT score FROM colours WHERE colour='red'; 

Oppure sarebbe più efficiente avere una sola istruzione INSERT quando viene effettuata una votazione, e poi recuperare il punteggio;

SELECT SUM(vote) AS score FROM votes WHERE colour='red'; 

Credo che quando c'è un piccolo numero di voti quindi l'opzione # 2 è migliore, ma vuol opzione # 1 diventano meglio quando il tavolo voti è molto grande?

C'è qualche strumento che posso usare per dare un tipo di classifica su alcune query SQL a seconda delle dimensioni della tabella, ecc?

+0

Ah scuse. Ho dimenticato di menzionare che le tabelle che registrano i voti individuali sono obbligatorie, quindi il tavolo deve essere lì indipendentemente dall'opzione che prendo. – Alwayslearning

+0

Quanto ti aspetti che il tuo tavolo sia grande? Lì * sarà * un punto oltre il quale 'SUM()' sarà notevolmente più lento. –

risposta

4

Personalmente, penso che se si desidera visualizzare un punteggio aggregato (e immagino che si vorrebbe visualizzare il punteggio frequentemente), quindi man mano che il numero di righe nella tabella di votazione aumenta, scoprirai che la query aggregata SUM impiegherà più tempo e più a lungo e non scalerà molto bene.

Inoltre, se si prevede di implementare una query che mostra solo colori con un punteggio pari o superiore a 100, l'aggregazione consente di eseguire query più semplici e più rapide.

Un altro vantaggio dell'utilizzo della colonna del punteggio è che se in una data futura si desidera eliminare la tabella votes (ad esempio se diventa troppo grande), è possibile farlo senza perdere i punteggi dei colori.

Non penso che si tratti di ottimizzazione prematura, penso che stia progettando un sistema con una scala in mente, quindi quello che vorrei fare è creare alcuni set di dati campione di un numero realistico di voti, colori e query al minuto. Aspettiamo e eseguiamo alcuni test delle prestazioni per valutare quale sia l'approccio migliore, perché è più facile (leggi più economico) scegliere l'approccio giusto ora piuttosto che risolverlo quando le cose iniziano a andare storte.

+0

Per avere un'idea migliore, è possibile utilizzare la funzione 'BENCHMARK()' per verificare se effettivamente colpirà il punto oltre il quale la differenza sarà evidente. –

1

La differenza di prestazioni tra le due query è banale. È necessario determinare la struttura in base alle informazioni che si desidera conservare.

Se avete solo bisogno di un punteggio complessivo, quindi utilizzare

UPDATE colours SET score=score-1 WHERE colour='red'; 

Questo sarà molto veloce, perché la tabella colours è solo andare per avere un paio di righe.

D'altra parte, potrebbe esserci un motivo per archiviare il voto di ciascun utente (ad esempio assicurandosi che non votino due volte). In tal caso, inserire una riga per ciascun voto.

INSERT INTO votes (colour,vote,user_id) VALUES (red,-1); 

Ma non creare una struttura di righe non necessarie solo perché pensi che sarà più veloce.

0

Ottimizzate prematuramente o si tratta di un problema reale?

Il primo approccio potrebbe essere più veloce ma si modifica il modello di dominio per motivi di ottimizzazione. Va bene purché tu sappia cosa stai facendo e quali svantaggi ti porta (probabile necessità di aggiornare due tabelle in tutti i posti che funzionano con voti, portando ad esempio la mancanza di sincronizzazione)

Ma potresti considerare altre opzioni. Ad esempio, se il numero di colori non è così grande, potresti creare una cache per le loro valutazioni. Ciò manterrà il modello semplice, le semplici meccaniche di valutazione e fornirà la velocità necessaria, meno un po 'di memoria;)

0

Il punto chiave di questo tipo di ottimizzazione è che cosa è l'ottimizzazione. Memorizzare la somma rende più lunghi gli inserimenti/cancellazioni/aggiornamenti. Il calcolo della somma influisce sulle prestazioni delle query sui dati.

Se si stanno eseguendo le eliminazioni o gli aggiornamenti sui dati, si vede rapidamente la follia del pre-calcolo della somma. Qualsiasi modifica di questo tipo ai dati richiede modifiche a più record, quando si pensa di cambiarne solo uno.

La struttura, tuttavia, sembra avere solo inserti - una buona scelta di design, a proposito, perché si vede ogni cambiamento. In questo caso, la domanda è se si desidera prendere il sovraccarico su ciascun inserto o se si desidera il sovraccarico sul lato "reporting". La domanda è facile in alcuni casi.

Se si dispone di 1000 voti per ogni volta che si guarda la somma, calcolare la somma al volo. Se hai 1000 somme per ogni voto, quindi memorizzare la somma sembra l'approccio più efficiente.

La mia ipotesi è che il carico di lavoro sia da qualche parte tra gli estremi. Il mio pregiudizio naturale è quello di archiviare i dati come generati e quindi di disporre di tabelle aggiuntive per i riepiloghi e i rapporti. Raccomanderei uno dei seguenti due approcci:

(1) Conserva solo i dati della transazione e calcola le somme al volo. Disporre gli indici sulla tabella per rendere le somme il più efficienti possibile.

(2) Conservare solo le transazioni in una tabella e calcolare le somme in un'altra tabella (utilizzando un trigger o una stored procedure). Questo ti dà i valori aggiornati necessari per la maggior parte degli scopi. Gli inserti dovrebbero essere più efficienti di memorizzare la somma su ogni record (perché la tabella a livello di utente è inferiore alla tabella a livello di voto).

Il tuo suggerimento di calcolare la somma nel record di voti non sarebbe normalmente un'opzione che prenderei in considerazione. Sarebbe auspicabile quando hai bisogno della storia dei voti incrementali. Ma, se stai guardando la cronologia, fare il calcolo sum o calcolare la somma nel livello applicazione sarebbe anche possibile.

Problemi correlati