Domanda

Sto lavorando su un sito Web con un semplice database normalizzato.

C'è una tabella chiamata Pages e una tabella chiamata Views. Ogni volta che viene visualizzata una Pagina, un record univoco di tale Vista viene registrato nella tabella Viste.

Quando visualizzo una pagina sul sito, utilizzo un semplice COUNT MySQL () per sommare il numero di visualizzazioni per la visualizzazione.

La progettazione del database sembra a posto, tranne per questo problema: non riesco a recuperare le 10 pagine più viste tra le migliaia.

Devo denormalizzare la tabella Pagine aggiungendo una colonna Pages.views per contenere il numero totale di visualizzazioni per ogni pagina? Oppure esiste un modo efficace per eseguire una query per le prime 10 pagine più visualizzate?

È stato utile?

Soluzione

   SELECT p.pageid, count(*) as viewcount FROM 
   pages p
   inner join views v on p.pageid = v.pageid
   group by p.pageid
   order by count(*) desc   
   LIMIT 10 OFFSET 0;

Non posso provarlo, ma qualcosa del genere. Non memorizzerei il valore se non dovessi a causa di vincoli di prestazione (ho appena appreso il termine "ottimizzazione prematura", e sembra applicarlo se lo fai).

Altri suggerimenti

Dipende dal livello di informazioni che si sta tentando di mantenere. Se vuoi registrare chi ha visualizzato quando? Quindi la tabella separata va bene. Altrimenti, una colonna per Views è la strada da percorrere. Inoltre, se mantieni una colonna separata, scoprirai che la tabella verrà bloccata più spesso poiché ogni visualizzazione di pagina proverà ad aggiornare la colonna per la riga corrispondente.

Select pageid, Count(*) as countCol from Views
group by pageid order by countCol DESC
LIMIT 10 OFFSET 0;

Probabilmente includerei la colonna delle viste nella tabella Pagine.

Mi sembra una rottura della normalizzazione perfettamente ragionevole. Soprattutto dal momento che non riesco a immaginare che tu stia eliminando le visualizzazioni in modo da non aspettarti che il conteggio esca dal colpo. In questo caso l'integrità referenziale non sembra super critica.

La normalizzazione del database riguarda il modo più efficiente / meno ridondante di archiviare i dati. Questo è utile per l'elaborazione delle transazioni, ma spesso è direttamente in conflitto con la necessità di ottenere nuovamente i dati in modo efficiente. Il problema viene di solito risolto avendo tabelle derivate (indici, viste materializzate, tabelle di rollup ...) con dati pre-elaborati più accessibili. La parola d'ordine (leggermente datata) qui è Data Warehousing.

Penso che tu voglia mantenere la tabella di Pages normalizzata, ma hai una tabella extra con i totali. A seconda di quanto devono essere recenti questi conteggi, è possibile aggiornare la tabella quando si aggiorna la tabella originale oppure è possibile disporre di un processo in background per ricalcolare periodicamente i totali.

Lo desideri anche solo se riscontri davvero un problema di prestazioni, cosa che non otterrai se non hai un numero molto elevato di record o un numero molto elevato di accessi simultanei. Mantieni il tuo codice flessibile per poter alternare tra avere la tabella e non averla.

La denormalizzazione funzionerebbe sicuramente in questo caso. La tua perdita è lo spazio di archiviazione aggiuntivo utilizzato dalla colonna aggiuntiva.

In alternativa, è possibile impostare un lavoro pianificato per popolare queste informazioni su base notturna, ogni volta che il traffico è basso, x periodo di tempo.

In questo caso perderai la possibilità di conoscere immediatamente il conteggio delle pagine a meno che non esegui questa query manualmente.

La denormalizzazione può sicuramente essere impiegata per aumentare le prestazioni.

- Kris

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