Newsgroup: it.comp.www.php
Titolo: Ottimizzare performance query mysql

Ultimamente sto utilizzando una query mysql in php per un insert di diverse
migliaia di righe in una tabella, il mio problema è ottimizzare la velocità.
So che mysql è un db molto veloce, come si può aumentare l'efficienza del
codice? A livello teorico mi piacerebbe poter creare 10.000 righe di una
tabella in 30 secondi: è possibile? Attualmente io uso un ciclo for con
all'interno un insert per ogni riga, ho provato anche a concatenare tutte le
query ed inserirle con un solo insert, ma: sembra ci sia un limite a 1064
righe e le prestazioni sembrano identiche...

 wrote in message
news:apdqc2$tg9$1...@lacerta.tiscalinet.it...

Sul manuale di MySQL viene descritta la procedura per l'importazione da file
(di testo sicurmanete), per cui potresti salvare su file i dati e farglieli
importare tutti in una volta, l'efficenza dovrebbe
essere molto migliore.
Facci sapere se è una soluzione valida.

 Facci sapere se è una soluzione valida.
Il mio problema è che vorrei fare gli insert tramite php, in real time.
Penso che far creare il file in php e poi passarlo a mysql sia cmq un
procedimento più lungo..
Guardando sul sito di mysql ho trovato questo:
"If you are inserting many rows from the same client at the same time, use
multiple value lists INSERT statements. This is much faster (many times in
some cases) than using separate INSERT statements."
http://www.mysql.com/doc/en/Insert_speed.html
Ma non riesco a capire cosa intendono per "multiple value lists
insert"(diverso da "The INSERT ... VALUES form of the statement inserts rows
based on explicitly specified values"
http://www.mysql.com/doc/en/INSERT.html
 ): che sia possibile una query del
tipo: la prima volta mi inserisci (1,pippo,paperopoli,fumetto) dopo
solo(,paperino,,,) e anzichè null inserire i valori della prima query?
Mmh... ma forse la velocità non cambierebbe...

 Mmh... ma forse la velocità non cambierebbe...
Cerchiamo di risolvere la cosa da un altro punto di vista:
Che cosa devi fare? Esempio pratico, tabella reale dati il più verosnimili,
procedura (cambio dati tra un insert e l'altro) e così via.

 procedura (cambio dati tra un insert e l'altro) e cosě via.
Ok, per esempio:
for($i=0;$i<3000;$i++)
{
    $query = mysql_query(insert into table (nome,numero,city,provincia)
values(Mario,76903,milano,lombardia);
    $numero=$numero+111;
}
Di questi dati city e provincia sono sempre uguali per tutte le query, gli
unici a cambiare sono nome e numero...

 unici a cambiare sono nome e numero...
// Bene, allora, le due prove qui sotto non sono state testate ma dovrebbero
funzionare a grandi linee.
$numero = 0;
$sSQL = "";
$sSQL = $sSQL . "INSERT INTO table (nome,numero,city,provincia) VALUES ";
$sJoin = "";
for($i=0;$i<3000;$i++)
{
    $name = "qui ci va il nome che deve cambiare";
    $sSQL = $sSQL . $sJoin . "('$nome', $numero, 'Milano', 'Provincia')"
    $sJoin = " ,";
    $numero=$numero+111;
}
$query = mysql_query($sSQL);
/*
L'unico problema che potrebbe sorgere deriva dalla lunghezza della query,
per sorpassare il problema potresti fare una cosa del genere:
*/
//Lock della tabella
mysql_query('LOCK TABLES table  WRITE;');
$numero = 0;
for ($cnt=0;$cnt<100;$cnt++)
{
    $sSQL = "";
    $sSQL = $sSQL . "INSERT INTO table (nome,numero,city,provincia) VALUES
";
    $sJoin = "";
    for($i=0;$i<30;$i++)
    {
        $name = "qui ci va il nome che deve cambiare";
        $sSQL = $sSQL . $sJoin . "('$nome', $numero, 'Milano', 'Provincia')"
        $sJoin = " ,";
        $numero=$numero+111;
    }
    //Query di inserimento di 30 valori alla volta (volendo si puň
aumentare )
    $query = mysql_query($sSQL);
}
//Unlock della tabella
mysql_query('UNLOCK TABLES;');

 unici a cambiare sono nome e numero...
Ciao,
forse sarebbe già molto utile per le prestazioni normalizzare la tabella in
quanto la ripetizione di city e provincia ti raddoppia il tempo della query.
--
paolo tosciri    ---   ICQ 119427174
e-mail: 
webm...@liara.com
sito di riferimento: 
www.liara.com

 quanto la ripetizione di city e provincia ti raddoppia il tempo della
query.
Grazie, ma come faccio a normalizzare la tabella? Scusa se la domanda è
stupida, ma non ho capito...

 }
<cut>
Grazie, non ci avevo pensato!! La concatenazione l'ho provata, ma come ti
dicevo mi dava un errore oltre 1064 righe di codice... proverò a imporre un
limite come mi hai suggerito. Un'ultima domanda: non è che si può settare
mysql per aumentare questo limite?
Ciao,
Andrea

 wrote in message
news:apeiu3$acl$1...@lacerta.tiscalinet.it...

Non credo, ma se è possibile sarebbe comunque necessario ricompilarlo.
Saluti

 ha scritto nel messaggio
news:apeicq$a5d$1...@lacerta.tiscalinet.it...

Allora ... normalizzare significa, in parole povere, spostare  i campi
ripetuti in una tabella in una nuova tabella e nella tabella madre inserire
un codice corrispondente.
Faccio l'esempio del tuo db.
Hai 4 campi nome,numero,city,provincia.
Mentre nome e numero son quasi sempre diversi, è sicuramente comune a molti
record il valore di city e provincia.
A questo punto crei una tabella TABELLA2 che contiene un campo id_citta un
campo city e un campo Provincia.
Nella tabella TABELLA1 al posto di inserire il campo city e provincia
inserisci il solo codice corrispondente,
Se nella TABELLA2 a milano - lombardia corrisponde il valore id=1 nella
TABELLA1 devi inserire solo nel campo id_citta il valore 1 e non i campi
city - lombardia.
In ogni caso, siccome mi sono reso conto che la mia spiegazione è alquanto
incasinata, fammi sapere e magari cerco di esprimermi meglio su domande
dirette.
ciao


 > <cut>
Allora, ho provato ma ho incontrato un problema: pare che mysql_query non
accetti insert multipli!! Forse č l'ora tarda di un sabato sera passato
davanti al pc, ma cosě pare: ho provato a concatenare le query in tutti i
modi possibili...

 dirette.
Allora, ho capito il concetto: purtroppo il mio era solo un esempio e in
pratica il riferimento da altre tabelle lo uso già in diversi campi... cmq
cercherò di ottimizzare tutto il possibile in questo modo. Quindi in pratica
dici che il db nell' inserire un valore numerico, diciamo a 2 cifre, è
sensibilmente più rapido rispetto all'inserire una parola come "lombardia"?

 modi possibili...
E' sicuramente l'ora tarda il codice
 $sSql = "INSERT INTO articles (IDArticle, IDUserRole, IDReview,IsEnabled)
VALUES (0,1,1,1),(0,1,1,2),(0,1,1,3);";
 dbconnect(_DBNAME,_DBUSER,_DBPASS,_DBHOST);
 $result = mysql_query($sSql);
funziona perfettamente, verifica se la query viene creata in modo corretto,
(spazi e virgole nei posti giusti), al massimo fai un echo , la copi e la
esegui direttamente su  MySQL e vedi se va.
Saluti.

 sensibilmente più rapido rispetto all'inserire una parola come
"lombardia"?
Il campo a 2 cifre Codice (tipo campo Tinyint - unsigned) "pesa" 1 byte.
Il campo città con valore "Milano" (tipo campo VARCHAR) (6+1) = 7 bytes.
Il campo provincia/regione con valore "Lombardia" (tipo campo VARCHAR) (9+1)
= 10 bytes.
Considera che se ti crei una tabella con insieme comune e provincia/Regione
(esiste già pronto!)
al posto di Milano/Lombardia = 17 bytes tu carichi solo il codice a due
cifre da 1 byte.
Sempre facendo ipotesi:  su 3000 record da inserire senza normalizzare
avresti 17 * 3000 = 51000 bytes da inserire, con la normalizzazione ne
avresti 1* 3000 = 3000 bytes.
Mi sembra un bel risparmio!!
In ogni caso ti conviene consultare anche il manuale in rete di Mysql che
elenca tutti i campi  con opzioni e vantaggi/svantaggi rispetto ai tipi di
dati inseriti.


 E' sicuramente l'ora tarda il codice
<cut>
Avevi ragione!
Grazie, ora il tutto è decisamente più veloce...