- Home
- Categorie
- Coding e Sistemistica
- MYSQL e altri Database
- mySql Lentissimo, mySql Rapidissimo
-
mySql Lentissimo, mySql Rapidissimo
Ciao a tutti,
ho bisogno di un po di conforto, sono disperato....
Vi spiego, ho realizzato un sito con un database abnorme, qualcosina tipo 200-300MB ( e sono solo dati testuali ), il fatto è che il sito di test era sotto un server di una ditta di hosting, e il sito vero e proprio è sotto un altro hosting.
Il problema: una query abbastanza corposa mi impiega 54 Secondi nel server ufficiale
Mentre in quello che solitamente usavo per i test appena 1.5 secondi....
E ovviamente il database è identico ( importazione fatta da pochi giorni) e identici sono indici e chiavi e tutto quel che ne consegue.....
I test dei tempi li ho fatti tramite il pannello di phpMyAdmin...
Come diavolo posso fare?
-
Ciao develUp,
incolla la query, e vediamo se è migliorabile...
-
Ecchela:
SELECT testataCalendario.dataPartitta, testataCalendario.campionato, righeCalendario.societa1, righeCalendario.societa2, righeCalendario.goal1, righeCalendario.goal2, righeFormazioni.sostAvuta, righeFormazioni.sostFatta, righeFormazioni.ammonito, righeFormazioni.espulso, righeFormazioni.posizione, righeFormazioni.partita, righeFormazioni.giornata, societa.societa as nomeSocietaGiocatore, societa.id as idSocietaGiocatore, count(righeGoal.id) as quantiGoal FROM testataCalendario, righeCalendario, societa, righeFormazioni LEFT OUTER JOIN righeGoal ON righeGoal.partita = righeFormazioni.partita AND righeGoal.persone = righeFormazioni.persone AND righeGoal.stagione = righeFormazioni.stagione WHERE righeFormazioni.stagione = '2009-10' AND righeFormazioni.persone = 'BUFFON Gianluigi' AND righeFormazioni.stagione = righeCalendario.stagione AND righeFormazioni.partita = righeCalendario.id AND testataCalendario.stagione = righeFormazioni.stagione AND societa.id = righeFormazioni.societa AND testataCalendario.id = righeCalendario.giornata AND ( righeFormazioni.posizione < 12 OR righeFormazioni.sostFatta != '0') GROUP BY righeFormazioni.id ORDER BY testataCalendario.numeroGiornata DESC
-
Che dimensioni hanno le 2 tabelle?
-
In che senso 2 tabelle?
Nella query ne vengono coinvolte 5...
Comunque:
testataCalendario: 2.907 inserimenti
righeCalendario: 26.275 ins.
societa: 900
righeFormazioni: 557.891
righeGoal: 37.547O forse ho capito male cosa mi stavi chiedendo?
-
@develUp said:
E ovviamente il database è identico ( importazione fatta da pochi giorni) e identici sono indici e chiavi e tutto quel che ne consegue.....
I test dei tempi li ho fatti tramite il pannello di phpMyAdmin...
Come diavolo posso fare?Sembra un problema di indici, riesci a postare uno show create table di tutte le tabelle coinvolte?
Per sapere quali indici vengono utilizzati e se vengono utilizzati riesegui la tua query utilizzando explainEXPLAIN SELECT testataCalendario.dataPartitta, ......
e posta i risultati, così possiamo aiutarti.
Ciao
-
Per quanto riguarda l'EXPLAIN
www.giorgiotave.it/media/images/sharingImages/1905.jpgDi seguito gli show create:
righeFormazioni
CREATE TABLErigheFormazioni
(\nid
int(11) NOT NULL auto_increment,\ngiornata
int(11) NOT NULL,\npartita
int(11) NOT NULL,\nstagione
varchar(255) NOT NULL,\nsocieta
varchar(255) NOT NULL,\nposizione
int(11) NOT NULL,\npersone
varchar(255) NOT NULL,\nsostAvuta
int(11) NOT NULL COMMENT 'esce',\nsostFatta
int(11) NOT NULL COMMENT 'entra',\nammonito
int(11) NOT NULL,\nespulso
int(11) NOT NULL,\nvoto
double NOT NULL,\ndataAgg
int(11) NOT NULL,\n PRIMARY KEY (id
),\n UNIQUE KEYgiornata
(giornata
,partita
,societa
,posizione
,stagione
)\n) ENGINE=MyISAM DEFAULT CHARSET=latin1testataCalendario
CREATE TABLEtestataCalendario
(\nidUnivoco
int(11) NOT NULL auto_increment,\ndataPartitta
varchar(255) NOT NULL,\ncampionato
varchar(255) NOT NULL,\nid
int(11) NOT NULL COMMENT 'TESTATA,ID è collegata direttamente a RIGHECALENDARIO.giornata',\nnumeroGiornata
int(11) NOT NULL,\nstagione
varchar(255) NOT NULL,\ndataAgg
varchar(255) NOT NULL,\n PRIMARY KEY (idUnivoco
),\n UNIQUE KEYcampionato
(campionato
,id
,numeroGiornata
,stagione
)\n) ENGINE=MyISAM DEFAULT CHARSET=latin1righeCalendario
CREATE TABLErigheCalendario
(\nidUnivoco
int(255) NOT NULL auto_increment,\nnazione
varchar(15) NOT NULL,\ncampionatoCalendario
varchar(100) NOT NULL,\ngiornata
int(11) NOT NULL,\nid
int(11) NOT NULL,\nsocieta1
varchar(255) NOT NULL,\nsocieta2
varchar(255) NOT NULL,\ngoal1
int(11) NOT NULL,\ngoal2
int(11) NOT NULL,\narbitro
varchar(255) NOT NULL,\nallenatore1
varchar(255) NOT NULL,\nallenatore2
varchar(255) NOT NULL,\nmodulo1
varchar(255) NOT NULL,\nmodulo2
varchar(255) NOT NULL,\ndataAgg
varchar(255) NOT NULL,\ndataPartita
varchar(255) NOT NULL,\nsospesa
varchar(255) NOT NULL,\naggiornata
varchar(255) NOT NULL,\nstagione
varchar(255) NOT NULL default '2008-09',\n PRIMARY KEY (idUnivoco
),\n UNIQUE KEYgiornata
(giornata
,societa1
,societa2
,stagione
)\n) ENGINE=MyISAM DEFAULT CHARSET=latin1societa
CREATE TABLEsocieta
(\nid
varchar(20) NOT NULL,\nsocieta
varchar(255) NOT NULL,\ndenominazione
varchar(255) NOT NULL,\nnazione
varchar(15) NOT NULL,\nindirizzo
varchar(255) NOT NULL,\ncitta
varchar(255) NOT NULL,\ntelefono
varchar(255) NOT NULL,\nfax
varchar(255) NOT NULL,\nstadio
varchar(255) NOT NULL,\nemail
varchar(255) NOT NULL,\nsitoWeb
varchar(255) NOT NULL,\ncoloriSociali
varchar(255) NOT NULL,\nnote
varchar(255) NOT NULL,\nmatricola
int(11) NOT NULL,\nallenatore
varchar(255) NOT NULL,\nallenatoreP
varchar(255) NOT NULL,\nrigaAllenatore
varchar(255) NOT NULL,\nimmagine
varchar(255) default NULL,\n PRIMARY KEY (id
)\n) ENGINE=MyISAM DEFAULT CHARSET=latin1righeGoal
CREATE TABLErigheGoal
(\nid
int(11) NOT NULL auto_increment,\ngiornata
int(11) NOT NULL,\npartita
int(11) NOT NULL,\nstagione
varchar(100) NOT NULL default '2008-09',\nsocieta
varchar(255) NOT NULL,\nposizione
int(11) NOT NULL,\npersone
varchar(255) NOT NULL,\ntipo
varchar(255) NOT NULL,\nminuto
int(11) NOT NULL,\ndataAgg
varchar(255) NOT NULL,\n PRIMARY KEY (id
),\n UNIQUE KEYpersone
(persone
,giornata
,stagione
,minuto
)\n) ENGINE=MyISAM DEFAULT CHARSET=latin1GRAZIE di cuore a tutti
-
@develUp said:
Per quanto riguarda l'EXPLAIN
http://www.giorgiotave.it/media/imag...mages/1905.jpgCiao,
ti confermo che è un problema di indici e di chiavi, in questo caso la ricerca nella tabella righeFormazioni è fatta sequenzialmente per 557891 record ed è molto lenta come anche nella tabella testataCalendario per molti meno record.Per cominciare ti consiglio di creare un unico index nella tabella righeFormazioni che comprenda in questo ordine:
persone
stagione
partitavedrai che ci metterà un po' di tempo per crearlo ma poi la query sara un po' più veloce.
Fai questa modifica e poi mandami un altro explain che controlliamo che sia tutto ok e ottimizziamo ulteriormente.Ciao
Matteo
-
Ciao Matteo grazie 1.000.000
Allora, mi sono letto qualche guida sugli indici e prima che tu mi rispondessi ne ho provati a creare qualcuno, e, strano ma vero avevo ottimizzato parecchio:
rows di righeFormazioni da 557.891 erano arrivate a 70.000 circa,
ho inserito l'indice come mi hai suggerito te, e sono adesso scese a 27!!!
( da notare che ti ho dedicato il nome dell indice )Immagine dell explain:
http://www.giorgiotave.it/media/images/sharingImages/1906.jpgMi spiegheresti in base a quali criteri hai scelto persone,stagione,partita?
Così almeno se mi dovessi ritrovare in una situazione analoga mi sbroglio da solo
-
@develUp said:
( da notare che ti ho dedicato il nome dell indice )
Grazie mille, ne sono onorato, ma ti conviene utilizzare un nome più "self explaing" tipo key_persone_stagione_partita
@develUp said:
Mi spiegheresti in base a quali criteri hai scelto persone,stagione,partita?
E' semplicemente l'ordine della clausola where della query che fai a quella tabella.
Esercizio: c'è un'altra tabella ottimizzabile, trovala e scrivi l'indice correttoDomanda: il tempo di esecuzione della query di quanto è ora?
Ciao
Matteo
-
E' di 0.0240 sec
Domanda: come mai non si è tenuto conto di questa clausola:
AND ( righeFormazioni.posizione < 12 OR righeFormazioni.sostFatta != '0') ?La prossima direi che è proprio righeCalendario e nell'indice metterei:
stagione, id ,giornata... c ho preso?Altra domanda, perchè abbiamo utilizzato INDEX anzichè UNIQUE?
Credevo, ( a quanto pare erroneamente ) che se dichiarassi un indice come unico avrei risparmiato fatica al povero server....
-
@develUp said:
E' di 0.0240 sec
Domanda: come mai non si è tenuto conto di questa clausola:
AND ( righeFormazioni.posizione < 12 OR righeFormazioni.sostFatta != '0') ?perchè non l'avevo vista, aggiungila all'index e guarda cosa succede.
@develUp said:
La prossima direi che è proprio righeCalendario e nell'indice metterei:
stagione, id ,giornata... c ho preso?Se non mi è scappata un altra condizione direi che: sì, ci hai preso.
@develUp said:
Altra domanda, perchè abbiamo utilizzato INDEX anzichè UNIQUE?
Credevo, ( a quanto pare erroneamente ) che se dichiarassi un indice come unico avrei risparmiato fatica al povero server....
Non è l'indice ad essere unico ma ciò che è indicizzato in questo caso deve essere unica la tripletta stagione, id ,giornata pena un errore in fase di inserimento.
Gli indici unici servono per mantenere coerenza dei dati.Ciao
Matteo
-
Questa storia degli indici, spesso e volentieri mi ha lasciato molto stupito.
In breve, come funzionano e in base a cosa si impostano?
-
@Amistat said:
In breve, come funzionano e in base a cosa si impostano?
In sintesi, gli indici permettono a mysql di cercare il dato che gli serve senza doversi scorrere la tabella riga per riga.
Non sono un DBA quindi non conosco il funzionamento a basso livello, quello che so è che utilizzando gli indici mysql accede alla tabella in modo casuale e non sequenziale accorciando di molto il tempo delle query.Si impostano in base ai parametri di ricerca delle query, la regola è che serve un indice ogni gruppo di richieste, nel caso sotto l'indice per righeCalendario è composto da stagione, id ,giornata perché quella query utilizza quei campi in quell'ordine.
Occhio a non esagerare perché ogni inserimento mysql aggiorna gli indici e se ce ne sono troppi il tempo di inserimento lievita.
Spero di averti aiutato.
Matteo
-
Ma facendo un esempio su una query molto più semplice (anche se magari serve meno) come potrebbe essere?