Metode de imbunatatiri ale interogarilor SQL

Întrebări legate de conectarea la baze de date MySQL prin intermediul PHP

Moderatori: Zamolxe, Moderatori

Avatar utilizator
adyre
Senior Member
Mesaje: 491
Membru din: Lun Dec 06, 2004 9:36 pm
Localitate: Buzau
Contact:

Metode de imbunatatiri ale interogarilor SQL

Mesajde adyre » Joi Dec 13, 2007 12:13 am

De ceva vreme tot am mai mult de lucru doar cu db-uri si asta ma face sa observ ca fiecare metoda de imbunatatire conteaza mai ales cand selectezi un simplu lucru din tabele de 100.000 de randuri concatenate....

Am observat ca multi folosesc 'camp'='valoare'. Imbunatateste query-ul.. si daca da, cam care query e mai bun:

Cod: Selectaţi tot

mysql_query('SELECT camp1, camp2 FROM tabela WHERE camp1="' . $valoare . '"') or die (mysql_error());

sau

mysql_query("SELECT 'camp1', 'camp2' FROM tabela WHERE 'camp1'='$valoare'") or die (mysql_error());


As vrea ca acest topic sa fie setat ca Stiky si ca toata lumea sa prezinte link-uri sau metode de a imbunatati interogarile MySQL standalone sau inauntr-ul PHP-ului... pentru ca o formarea unei interogari optimizate scrisa in PHP poate ajunge sa fie in contradictie cu metodele de imbunatatiri a script-ului.

As vrea sa se discute depsre tot ce fiecare crede ca e mai bine, de exemplu: pentru a afla numarul inregistrarilor dintr-o tabela e mai rapid folosind mysql_num_rows sau folosind count(*) (sincer, nush care ar fi mai rapida, dar cred ca e vorba de count(*).


Multumesc si sper ca acest post sa nu combata in vreun fel regulile de utilizare.


Viata e prea scurta sa faci un lucru singur. Cere AJUTOR!

Avatar utilizator
saitek
Senior Member
Mesaje: 454
Membru din: Dum Sep 23, 2007 6:40 am

Mesajde saitek » Joi Dec 13, 2007 2:21 am

Cod: Selectaţi tot

$query= mysql_query("SELECT * FROM `".$table."` WHERE `camp` = 'ceva' ");
Blog Beta|Translate to rgb
GOOGLE = un mare prost

Avatar utilizator
mihaitha
Senior Member
Mesaje: 2383
Membru din: Vin Mai 04, 2007 12:40 pm
Localitate: Sibiu
Contact:

Mesajde mihaitha » Joi Dec 13, 2007 9:44 am

saitek a identificat clar problema: din cele doua variante date de tine, in mod sigur prima e corecta, intrucat aceea iti face interogarea din tabela, in timp ce a doua iti va returna ori un result set gol, ori un result set plin cu stringurile 'camp1' si 'camp2', in functie de valoarea lui $valoare (daca este diferita de, respectiv egala cu 'camp1'). Adica trebuia sa folosesti ` nu '.

Trecand peste acest aspect, si intelegand exact la ce te referi, eu unul nu am facut teste de performanta sa vad daca interogarea dupa `camp` e mai rapida decat interogarea dupa camp. In mod normal ar fi cat de cat logic, in conditiile in care cauti dupa camp MySql ar trebui sa caute printre variabilele declarate local daca exista vreuna cu numele respectiv, insa daca nici una nu e declarata, asta n-ar trebui sa il afecteze sensibil la nivelul performantei. Mie personal nu-mi plac `` si evit sa le folosesc, de aceea imi aleg numele campurilor/tabelelor folosind _ ca divider, tocmai pentru a nu fi nevoie sa le folosesc.

Referitor la razboiul dintre mysql_num_rows si count(*), teoretic razboiul e castigat de count(*). De ce? Pai gandeste-te la nivel de core ce se intampla in cazul unui:

Cod: Selectaţi tot

$res = mysql_query('SELECT * FROM tabela');
echo mysql_num_rows($res);
MySql citeste toate inregistrarile din tabela (adica continutul lor complet), i le paseaza php-ului care creeaza structurile de date necesare si le stocheaza in memorie. Dupa aceea, la apelul mysql_num_rows(), php-ul numara cate astfel de structuri are stocate in memorie (din cate stiu eu e vorba de o lista simplu inlantuita, deci pentru a afla numarul lor trebuie parsata toata lista) si returneaza rezultatul.
In cazul lui:

Cod: Selectaţi tot

$res = mysql_query('SELECT COUNT(*) FROM tabela');
echo mysql_result($res, 0)
treaba se intampla asa: din nou, MySql citeste toate inregistrarile din tabela, fara a-l interesa continutul, ci doar existenta lor, retine un numar si i-l paseaza php-ului. Acesta primeste o valoare (adica maxim 8 octeti) si ii stocheaza in memorie. Dupa care, la mysql_result, acesti 4/8 octeti sunt cititi, convertiti in string si afisati.

Concluzie: cu mysql_num_rows MySql-ul lucreaza ceva mai putin, insa PHP-ul lucreaza muuuult mai putin, atat din punct de vedere al procesarii, cat si al memoriei ocupate.

Avatar utilizator
kleampa
Senior Member
Mesaje: 2774
Membru din: Dum Iul 10, 2005 2:12 pm
Localitate: Bucuresti
Contact:

Mesajde kleampa » Joi Dec 13, 2007 10:16 am

de preferat pentru cei mai incepatori sa faca comanda interogarii intr-o variabila pentru ca mai apoi sa ii poate da un print si sa vada ce contine in caz ca ceva nu merge bine

Avatar utilizator
UnTip
Senior Member
Mesaje: 389
Membru din: Joi Mai 03, 2007 1:55 pm

Mesajde UnTip » Joi Dec 13, 2007 10:21 am

si pentru ce-i "avansati" ce-ar fi de preferat ?
"Nothing has such power to broaden the mind as the ability to investigate systematically and truly all that comes under thy observation in life. "

Avatar utilizator
adyre
Senior Member
Mesaje: 491
Membru din: Lun Dec 06, 2004 9:36 pm
Localitate: Buzau
Contact:

Mesajde adyre » Joi Dec 13, 2007 10:24 am

Nu inteleg ce anume vrei sa spui cand spui ca folosesti _ ca divider.


Si nu vreau doar sa discutati despre ce exemple am dat eu, ci sa veniti si cu propriile voastre exemple si metode.. poate chiar si link-uri in care se explica indea-proape cum poate fi folosit sistemul de cashe a in terogarilor SQL si cand anume e cel mai bine de folosit.....care dintre operatori sunt mai folositi si cand sunt mai buni pentru utizare (de exemplu <> contra lui != ).

Si de exemplu pentru utilizarea in PHP a interogarilor de genul:

Cod: Selectaţi tot

$sql1 = mysql_query('SELECT id FROM tabela1 WHERE conditie = 1') or die (mysql_error());
$nr_linii = mysql_num_rows($sql1);
$start_linii = 1;

$id = ' IN(';
while($camp = mysql_fetch_array($sql1)) {

    if($nr_linii != $start_linii) {
          $id .= $camp['id'] . ',';
          $start_linii++;
    } else {
          $id .= $camp['id'] . ')';
    }

}

$sql2 = mysql_query('SELECT * FROM tabela2 WHERE id ' . $id) or die (mysql_error());
..................................
contra (care stiu sigur ca ar trebui sa fie mai rapid):

$sql = mysql_query('SELECT * FROM tabela2 WHERE id IN(SELECT id FROM tabela1 WHERE conditie = 1)') or die (mysql_error());


Si ce spuneam de utilizarea interogarilor in SQL:

pentru interogarea:

Cod: Selectaţi tot

mysql_query('SELECT camp1, camp2 FROM tabela WHERE camp1="' . $valoare . '"') or die (mysql_error());

se folosesc ghilimele simple, ceea ce se cunoaste ca php-ul parseaza mai rapid pentru ca nu face si verificare de variabile in interogare pana la intalnirea celei de a 2 ghilimea care se foloseste pentru concatenarea variabilei, iar la cel de-al doilea exemplu:

Cod: Selectaţi tot

mysql_query("SELECT 'camp1', 'camp2' FROM tabela WHERE 'camp1'='$valoare'") or die (mysql_error());

se folosesc ghilimele duble, care face ca php-ul sa fie pe faza tot timpul dupa variabile, ceea ce ii ingreuneaza si incarcarea......

Continuati, va rog, cu tot ceea ce credeti ca ar trebui sa stim si care ar trebui sa tinem cont. Multumesc.
Viata e prea scurta sa faci un lucru singur. Cere AJUTOR!

Avatar utilizator
Birkoff
Senior Member
Mesaje: 6377
Membru din: Joi Mar 18, 2004 2:34 pm
Localitate: Bucuresti
Contact:

Mesajde Birkoff » Joi Dec 13, 2007 12:03 pm

1) CMS, ERP, CRM, etc... (doar pentru clienti))
2) Portofoliu, servicii, contact, blog
3) Folositi aceasta clasa sql in proiectele voastre (open source)
4) Vrei un magazin virtual la cheie, usor de folosit, cu api-uri incluse pentru maximizarea vanzarilor si multe alte facilitati? Da un semn si discutam.

Avatar utilizator
adyre
Senior Member
Mesaje: 491
Membru din: Lun Dec 06, 2004 9:36 pm
Localitate: Buzau
Contact:

Mesajde adyre » Joi Dec 13, 2007 12:08 pm

Pe aproape, dar chiar nu mai exista alte metode... pentru ca lista asta cred ca e in primele 50 de cautari pe Google.
Viata e prea scurta sa faci un lucru singur. Cere AJUTOR!

Avatar utilizator
mihaitha
Senior Member
Mesaje: 2383
Membru din: Vin Mai 04, 2007 12:40 pm
Localitate: Sibiu
Contact:

Mesajde mihaitha » Joi Dec 13, 2007 12:13 pm

adyre scrie:Nu inteleg ce anume vrei sa spui cand spui ca folosesti _ ca divider.


Adica atunci cand creez o tabela sau un camp, in loc sa o denumesc tabela-cutare (adica sa folosesc - ca divider), ceea ce m-ar forta sa fac interogari de genul

Cod: Selectaţi tot

SELECT * FROM `tabela-cutare`
intrucat o interogarea

Cod: Selectaţi tot

SELECT * FROM tabela-cutare
ar crapa deoarece MySql ar incerca sa faca tabela minus cutare, ii zic tabela_cutare, si atunci interogarea

Cod: Selectaţi tot

SELECT * FROM tabela_cutare
merge perfect.

P.S. Vad ca nu observi/ignori intentionat faptul asupra caruia atat saitek, cat si eu ti-am atras atentia: faci confuzie intre ' si `, care in MySql au cu totul alte roluri:
adyre scrie:

Cod: Selectaţi tot

mysql_query("SELECT 'camp1', 'camp2' FROM tabela WHERE 'camp1'='$valoare'") or die (mysql_error());

Interogarea asta nu merge cum anticipezi tu. Ti-am explicat in postul anterior ce ar face un astfel de query. Oricum, desi folosirea de stringuri cu '' in loc de "" e intr-adevar mai rapida in php, dar daca compari cu concatenarea de stringuri, tot pe acolo iesi, daca nu chiar mai greoi. Folosirea stringurilor cu '' se recomanda acolo unde nu ai variabile adica nu

Cod: Selectaţi tot

echo "bubu";
ci

Cod: Selectaţi tot

echo 'bubu';
Decat

Cod: Selectaţi tot

mysql_query('SELECT * FROM tabela WHERE camp = "' . $val . '"')
eu zic ca e echivalent ca si performanta, dar mult mai greoi ca productivitate decat

Cod: Selectaţi tot

mysql_query("SELECT * FROM tabela WHERE camp = '$val'")


Apropo, sfat atat pentru incepatori cat si pentru avansati: liniile de forma

Cod: Selectaţi tot

mysql_query("... query oarecare ...") or die(mysql_error());
le recomand exclusiv cat timp scrii codul si il testezi! Odata ce query-ul merge, scapa de die(), Ca il uiti acolo. Si ramane si pe live, si mult mai urat da pentru utilizatorul de rand un mesaj de eroare de mysql (din care oricum nu intelege nimic) decat o pagina alba in momentul cand ti-e crapat mysql-ul sau ai flood si ti s-a umplut numarul de conexiuni. La o pagina alba da refresh. La un mesaj de eroare te injura si inchide browserul.

Avatar utilizator
Birkoff
Senior Member
Mesaje: 6377
Membru din: Joi Mar 18, 2004 2:34 pm
Localitate: Bucuresti
Contact:

Mesajde Birkoff » Joi Dec 13, 2007 12:14 pm

de curiozitate am dat search pe google dupa "optimizing mysql code" :D
1) CMS, ERP, CRM, etc... (doar pentru clienti))
2) Portofoliu, servicii, contact, blog
3) Folositi aceasta clasa sql in proiectele voastre (open source)
4) Vrei un magazin virtual la cheie, usor de folosit, cu api-uri incluse pentru maximizarea vanzarilor si multe alte facilitati? Da un semn si discutam.

Avatar utilizator
adyre
Senior Member
Mesaje: 491
Membru din: Lun Dec 06, 2004 9:36 pm
Localitate: Buzau
Contact:

Mesajde adyre » Joi Dec 13, 2007 12:21 pm

Pai asta e chestia: tu ce ai dat e pentru imbunatatirea PHP-ului (nu pentru SQL)
Viata e prea scurta sa faci un lucru singur. Cere AJUTOR!

Avatar utilizator
kyron
Senior Member
Mesaje: 639
Membru din: Joi Sep 16, 2004 1:12 pm
Localitate: Bucuresti
Contact:

Mesajde kyron » Joi Dec 13, 2007 12:59 pm

Optimizari pentru Mysql:

- Foloseste indecsi pe campurile pe care faci cautari frecvente

Un SELECT * FROM `tabel` WHERE Nume='adi' este mult mai rapid daca campul Nume este declarat index (ALTER TABLE `tabel` ADD INDEX(Nume);)

- Daca esti si mai maniac, poti folosi short indexes. Cand ai un camp de 40 caractere si vrei sa-l indexezi, poti face asta numai pentru primele 20, pentru rezultate mai rapide: ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20);

- Tot pentru viteza sporita, mai poti rula pe o tabela in care ai facut multe update/delete : OPTIMIZE TABLE `tabel`

- Foloseste JOIN-uri pe campuri indexate

Avatar utilizator
Quber
Senior Member
Mesaje: 874
Membru din: Mar Iun 27, 2006 8:33 pm
Localitate: localhost
Contact:

Mesajde Quber » Joi Dec 13, 2007 1:21 pm

@kyron, Am auzit ca JOIN foloseste mai multe resurse ca un SELECT...!

uite atent ai o greseala:

Cod: Selectaţi tot

ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20); = ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20));
A man who dares to waste one hour of time has not discovered the value of life.

Avatar utilizator
mihaitha
Senior Member
Mesaje: 2383
Membru din: Vin Mai 04, 2007 12:40 pm
Localitate: Sibiu
Contact:

Mesajde mihaitha » Joi Dec 13, 2007 1:24 pm

Quber, cum faci un join fara select?
Si btw, esti carcotas.

Avatar utilizator
kyron
Senior Member
Mesaje: 639
Membru din: Joi Sep 16, 2004 1:12 pm
Localitate: Bucuresti
Contact:

Mesajde kyron » Joi Dec 13, 2007 1:43 pm

Quber scrie:@kyron, Am auzit ca JOIN foloseste mai multe resurse ca un SELECT...!


ai auzit prost.

Quber scrie:uite atent ai o greseala:

Cod: Selectaţi tot

ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20); = ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20));


da, am uitat o paranteza. Mare lucru. Nu aia era esenta postului. Te astept cu idei/propuneri concrete de optimizare baze de date.


Înapoi la “MySQL”

Cine este conectat

Utilizatori ce ce navighează pe acest forum: Niciun utilizator înregistrat și 2 vizitatori