Care este cel mai rapid mod de interogare ?

Am nevoie pentru a afectua o simpla interogare.
Tabelul este de +1 milion de utilizatori
Tot ce am pentru a efectua interogarea este:

$result  = $pdo->query("SELECT * FROM users ORDER BY vizite DESC LIMIT 0,20");
foreach ($result as $row) {
$uid   = $row['id'];
$user = $row['utilizator'];
echo $uid." - ".$user."<br/>\n";
}

SELECT * nu prea este indicat. Atata timp cat te intereseaza doar “id” si “utilizator” interogheaza doar dupa aceste coloane.

Este adevarat doar ca eu am id, user, pass si vizite … nu sunt asa multe chestii, am pus si “id, utilizator” inloc de “*” dar tot la fel de greu interogheaza.

Liniile astea imi par un pic cam ciudate. Ce reprezinta $pdo? Poti pune mai mult cod?

$pdo face conexiunea la baza de date:

try{
  $pdo = new PDO("mysql:host=$db_host;dbname=$db_name;charset=$charset",$db_user,$db_pass, 
		array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
} catch(PDOException $e){ 
  die("Nu se poate face conexiunea la baza de date !");
}
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);

Bun, atunci poti face direct

$result  = $pdo-&gt;query("SELECT * FROM users ORDER BY vizite DESC LIMIT 0,20");
foreach ($result as $row) {
    $uid   = $row['id'];
    $user = $row['utilizator'];
    echo $uid." - ".$user."&lt;br/&gt;\n";
}
  1. Pune în select doar coloanele de care ai nevoie, chiar dacă sunt multe.
    1.1 Indecși pe tabelă (pe coloanele după care faci căutări des dar și pe coloanele după care faci order?
  2. Citește datele folosind while, ca să nu ramai fără memorie (elimini $result, care practic ține toate datele): while ($row = $query->fetch(PDO::FETCH_ASSOC)) { /* magic */ }
1 Like

Noul cod pe care l-am pus este:

$result = $pdo->query("SELECT id,utilizator FROM users ORDER BY vizite DESC LIMIT 0,20"); foreach ($result as $row) { $uid = $row['id']; $user = $row['utilizator']; echo $uid." - ".$user."<br/>\n"; }
Dar nu imi pare sa interogheze mai rapid, tot cu greu.

When everything fails use database caching.

Nu esti primul care imi spune asta, dar nu stiu cum se face chestia asta…

Ai pus indecsii asa cum a sugerat @redecs?

Asa cu spunea si @redecs, pune index pe coloanele pe care le folosesti in WHERE sau ORDER BY pentru optimizarea query-urilor (in cazul tau adauga un index INDEX pe coloana vizite). Vezi aici cum/cand foloseste MySQL indecsii si aici pentru a vedea cum pot fi optimizate query-urile care folosesc ORDER BY.
Daca timpul nu se imbunatateste poate exista o problema cu serverul / baza de date…

3 Likes

Imi poti arata un exemplu te rog, invat mai greu,

CREATE INDEX viziteIndex ON users (vizite); ar trebui sa mearga.

1 Like

Nu ai ce optimiza la query în acest caz dacă ai deja index pe id, probabil baza ta de date rulează pe un server cu I/O slab, fără indecșii în memorie sau o versiune de MySQL veche.

Dacă rulezi pur și simplu select-ul în phpmyadmin sau navicat/heidisql/dbeaver ar trebui să meargă aproape instant.

Daca rulez in phpmyadmin se incarca aproape instant la o secunda.

Tocmai au scris altii mai sus ca ar trebui sa puna un index pe coloana vizite pe care face ORDER BY

De ce ar trebui sa mearga mai repede?

@Gabriela mai bine ne dai si noua structura: show create table users; si versiunea: show variables like "%version";

Da, poate pune un index care va fi folosit în acest caz pentru a rula mai rapid, dar nu poate optimiza query-ul în sine.

Sortarea pe niște valori numerice nu trebuie să îi facă probleme mysql-ului la 1 milion de utilizatori, adică vei vedea rezultatul sub 1s. Nu va rula mai rapid în phpmyadmin, va rula rapid orice i-ai face că doar e vorba de un quick sort amărât.

Te conectezi cumva pe dns în loc de ip la serverul mysql ? Folosește direct socket-ul sau 127.0.0.1 dacă e pe același server. În php cel mai rapid mod de interogare este PDO dacă rețeaua la serverul mysql e un bottleneck, altfel e egal cu mysqli.

2 Likes

Salut,
Daca tot ai nevoie de optimizare suplimentara atunci poti pastra in tabela doar elementele esentiale si restul intr-o tabela secundara.
Astfel in tabela de 1 mil faci query pe 2 coloane si dupa faci query in tabela secundara. .

Spor

Împărțirea asta rezultă în ceva (mult) mai rapid decât select col1, col2 from tabel?

Al doilea query (cel în tabela secundară) nu va afecta performanța?