Pagina de start a forumului Forum PHP Romania - Discutii despre PHP, MySQL, Javascript, AJAX, etc Forum PHP Romania - Discutii despre PHP, MySQL, Javascript, AJAX, etc
Comunitatea PHP Romania
 

Metode de imbunatatiri ale interogarilor SQL
Vezi mesajul original
Du-te la pagina 1, 2, 3  Următoare
 
       Pagina de start a forumului Forum PHP Romania - Discutii despre PHP, MySQL, Javascript, AJAX, etc -> MySQL
Subiectul anterior :: Subiectul următor  
Autor Mesaj
adyre



Data înscrierii: 06/Dec/2004
Mesaje: 440
Locație: Buzau

Trimis: Joi Dec 13, 2007 12:13 am    Titlul subiectului: Metode de imbunatatiri ale interogarilor SQL  

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:
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.
Sus  
saitek



Data înscrierii: 23/Sep/2007
Mesaje: 437

Trimis: Joi Dec 13, 2007 2:21 am    Titlul subiectului:  

Cod: $query= mysql_query("SELECT * FROM `".$table."` WHERE `camp` = 'ceva' ");
Sus  
mihaitha



Data înscrierii: 04/Mai/2007
Mesaje: 1389
Locație: Sibiu

Trimis: Joi Dec 13, 2007 9:44 am    Titlul subiectului:  

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: $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: $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.
Sus  
kleampa



Data înscrierii: 10/Iul/2005
Mesaje: 2053
Locație: Bucuresti

Trimis: Joi Dec 13, 2007 10:16 am    Titlul subiectului:  

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
Sus  
UnTip



Data înscrierii: 03/Mai/2007
Mesaje: 367

Trimis: Joi Dec 13, 2007 10:21 am    Titlul subiectului:  

si pentru ce-i "avansati" ce-ar fi de preferat ?
Sus  
adyre



Data înscrierii: 06/Dec/2004
Mesaje: 440
Locație: Buzau

Trimis: Joi Dec 13, 2007 10:24 am    Titlul subiectului:  

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:
$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:
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:
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.
Sus  
Birkoff



Data înscrierii: 18/Mar/2004
Mesaje: 2276
Locație: Bucuresti

Trimis: Joi Dec 13, 2007 12:03 pm    Titlul subiectului:  

http://www.phpromania.net/blog/2007/10/21/optimizarea-codului-scris-in-php/
Sus  
adyre



Data înscrierii: 06/Dec/2004
Mesaje: 440
Locație: Buzau

Trimis: Joi Dec 13, 2007 12:08 pm    Titlul subiectului:  

Pe aproape, dar chiar nu mai exista alte metode... pentru ca lista asta cred ca e in primele 50 de cautari pe Google.
Sus  
mihaitha



Data înscrierii: 04/Mai/2007
Mesaje: 1389
Locație: Sibiu

Trimis: Joi Dec 13, 2007 12:13 pm    Titlul subiectului:  

adyre a scris: 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: SELECT * FROM `tabela-cutare` intrucat o interogarea Cod: SELECT * FROM tabela-cutare ar crapa deoarece MySql ar incerca sa faca tabela minus cutare, ii zic tabela_cutare, si atunci interogarea Cod: 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 a scris: Cod: 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: echo "bubu"; ci Cod: echo 'bubu'; Decat Cod: mysql_query('SELECT * FROM tabela WHERE camp = "' . $val . '"') eu zic ca e echivalent ca si performanta, dar mult mai greoi ca productivitate decat Cod: mysql_query("SELECT * FROM tabela WHERE camp = '$val'")

Apropo, sfat atat pentru incepatori cat si pentru avansati: liniile de forma Cod: 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.
Sus  
Birkoff



Data înscrierii: 18/Mar/2004
Mesaje: 2276
Locație: Bucuresti

Trimis: Joi Dec 13, 2007 12:14 pm    Titlul subiectului:  

de curiozitate am dat search pe google dupa "optimizing mysql code" :D
Sus  
adyre



Data înscrierii: 06/Dec/2004
Mesaje: 440
Locație: Buzau

Trimis: Joi Dec 13, 2007 12:21 pm    Titlul subiectului:  

Pai asta e chestia: tu ce ai dat e pentru imbunatatirea PHP-ului (nu pentru SQL)
Sus  
kyron



Data înscrierii: 16/Sep/2004
Mesaje: 528
Locație: Bucuresti

Trimis: Joi Dec 13, 2007 12:59 pm    Titlul subiectului:  

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
Sus  
Quber



Data înscrierii: 27/Iun/2006
Mesaje: 781
Locație: localhost

Trimis: Joi Dec 13, 2007 1:21 pm    Titlul subiectului:  

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

uite atent ai o greseala:
Cod:
ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20); = ALTER TABLE `tabel` ADD INDEX(Nume_Camp(20));
Sus  
mihaitha



Data înscrierii: 04/Mai/2007
Mesaje: 1389
Locație: Sibiu

Trimis: Joi Dec 13, 2007 1:24 pm    Titlul subiectului:  

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



Data înscrierii: 16/Sep/2004
Mesaje: 528
Locație: Bucuresti

Trimis: Joi Dec 13, 2007 1:43 pm    Titlul subiectului:  

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


ai auzit prost.

Quber a scris:
uite atent ai o greseala:
Cod:
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.
Sus  
PHPRomania Bot
Bot Member


Data înscrierii: 27/Dec/2007
Mesaje: 1
Locaţie: Server Google
Trimis: Mie Dec 26, 2007 7:01 pm   Titlul subiectului: Ad  

Sus  
 
       Pagina de start a forumului Forum PHP Romania - Discutii despre PHP, MySQL, Javascript, AJAX, etc -> MySQL Du-te la pagina 1, 2, 3  Următoare
Pagina 1 din 3


Powered by phpBB 2.0.22 © 2001, 2002 phpBB Group
Varianta în limba română: Romanian phpBB online community