Newsgroup: it.comp.www.php
Titolo: mysql e ottimizzazione db

Ciao a tutti, 
Ragazzi devo creare un sistema di statistiche che monitora gli accessi
di circa
300/400 siti alcuni dei quali toccano le 20.000 pagine visitate
mensili
(ma parecchi non vanno oltre le 1000) praticamente un servizio tipo
shinystat
come db verra utilizzato mysql. 
Mi sembra fondamentale in questa fase pianificare bene la crezione del
db.
avevo pensato a queste 4 soluzioni : 
1) unico database 
1 tabella in cui vengono registrati tutti gli accessi 
1 tabella dove ogni mese viene creato lo storico con tutti i mesi
passati
2) unico database 
1 tabella per ogni mese dell'anno 
3) multi database 
1 db per ogni sito con una tabella per gli accessi ed un altro per lo
storico
3)multi database 
1 db per ogni sito con un tabelle per ogni mese dell'anno 
SEcondo voi quale della 4 soluzioni mi garantisce una maggiore
efficienza sopratutto
in fase di creazione dei report delle statistiche e in vista della
mole di dati
che deve contenere il db ? 
io avevo pensato alla soluzione numero 2 anche perche creare 400 e
oltre database su
un unica macchina (3 e 4) mi sembra un pò eccessivo, voi che ne
pensate ?
Grazie a tutti

avevo pensato a queste 4 soluzioni : 
Dipende tutto da che statistiche fai.
Per esempio, se ti servisse soltanto il conteggio degli accessi, senza
alcuna altra info, puoi usare tre tabelle:
	1) Tabella STORICO
	2) Tabella CORRENTI	<-- i contatori pescano da qui
	3) Tabella CONTATORI
		sito	varchar
		accessi integer
Ogni giorno, un cron job svuota CORRENTI dentro LAVORO, poi estrae i totali
da LAVORO e li sbatte in CONTATORI, quindi somma LAVORO a STORICO, e infine
cancella LAVORO.
Tutte le statistiche pescano da CONTATORI. Ogni tanto puoi eliminare i mesi
piu' vecchi da STORICO e sbatterli su CD o simili. Oppure potresti avere 12
tabelle STORICO_JAN..STORICO_DEC, e ciascuna con un massimo di 8 milioni di
record.
I contatori on-line pescano da CORRENTI, sommano al pescaggio da CONTATORI,
e con due query su tabelle limitate (CONTATORI ha una riga per sito...) non
hanno altro a fare.
Se volessi fornire accessi e referrals, ti servirebbe una tabella CONTATORI
	sito		varchar
	referrer	varchar
	accessi		integer
e ogni sito potenzialmente potrebbe avere un numero altissimo di record; in
quel caso tanto varrebbe avere solo STORICO e fare i conti su quello, e, di
conseguenza, per ridurre le dimensioni della singola tabella, avere storici
mensili per sito. Chiaro che a quel punto hai 400 x 12 = 4800 tabelle, con,
al massimo, 20000 record per tabella. E non puoi fare query su piu' siti ma
dovresti selezionare i siti uno per uno e sommarne i risultati.
(Anche se nulla ti vieterebbe di accorpare cinque o sei siti in una singola
tabella, usando un campo "sito" per distinguere)
Il conteggio in MySQL pero' sarebbe istantaneo perche' count() non utilizza
i dati all'interno della tabella, non rallenta all'aumentare di questa.
Un'altra cosa che conviene e' usare una tabella di traduzione del tipo
	id	serial
	value	varchar
e mantenere, nelle tabelle, piu' cose "tradotte" possibile - per es. non e'
necessario stivare, come User-Agent, "Netscape 7.0 (Compatible; Linux 2.4.4
kernel with SMP; Q12345678; I like beef with grilled mushrooms)", basta una
laconica colonna di tipo integer. Idem per il nome del sito e i referrer.
Leonardo
-- 
Time's angles, mages tell, conceal a place
incredible, beyond the mundane mind;
night-shrouded and between the seas of space
dread creatures drift in the ageless winds.

 laconica colonna di tipo integer. Idem per il nome del sito e i referrer.
infatti ho fatto cosi
ma secondo te con una struttura del tipo:
1 tabella per ogni mese dell'anno dove registro tutti i siti
posso andare incontro a problemi quando mi ci trovo dentro 8 milioni
di record in fase di creazione dei report ??
oppure avevo anche pensato ad una struttura del tipo una tabella
singola (mese corrente) per ogni account con una tabella storico per
ogni mese cosi da avere sempre le statistiche mensili del mese
correnti molto veloci....

di record in fase di creazione dei report ??
Piu' che altro in quel caso ogni report deve andare a ignorare la gran
parte dei dati.
Un compromesso e' questo: una tabella sola e' poco, ma una per sito e'
sicuramente eccessivo. Allora, ti prepari una tabella secondaria, dove
memorizzi
		sito		tabella
 
www.a.it
	pocotraffico
 
www.b.it
	pocotraffico
 
www.c.it
	sites_srl
 
www.d.it
	at_d
 
www.e.it
	sites_srl
cosi', quando parti per un report, prima guardi che tabella consultare
e poi parti. Cosi', puoi ripartire il peso dei log su piu' tabelle, in
modo trasparente. Un domani che 
www.b.it
 aumenta il traffico,
	CREATE TABLE at_b (...);
	-- oppure SELECT * INTO at_b FROM pocotraffico WHERE false;
	UPDATE xlate SET tabella = 'at_b' WHERE sito='
www.b.it
';
	-- Da adesso, eventuali script concorrenti inseriranno in
	-- at_b, quindi "pocotraffico" non e' piu' usata da loro,
	-- e non mi serve alcun lock.
	INSERT INTO at_b SELECT * FROM pocotraffico WHERE idsito=666;
	DELETE FROM pocotraffico WHERE idsito=666;
Si potrebbe perfino studiare un metodo di knapsacking dinamico...! :-)
Leonardo (lo portano via)
