Diskuze: Redukce DB dotazů

PHP PHP Redukce DB dotazů American English version English version

Avatar
Martin Konečný (pavelco1998):

Ahoj,

mějme příklad, že na naší webové stránce musí mít uživatel minimálně pěti znakové jméno. Když potom přidáte vyhledávání uživatelů dle jména, máte asi takový dotaz:

$name = !empty($_GET["name"]) ? $_GET["name"] : NULL;
$users = array();
if ($name !== NULL) {
  $users = $db->fetchAll("
     SELECT id, name, ...
     FROM user
     WHERE name LIKE ?
  ", $name);
}

Otázká zní - co když do vyhledávacího pole zadám jméno, které má 4 a méně znaků?
Necháte vykonat databázový dotaz, i když je jasné, že takový uživatel existovat nemůže (protože uživatelé mají 5 a více znaků)? Nebo použijete takovouto podmínku?

const MIN_USERNAME_LENGTH = 5;

$name = !empty($_GET["name"]) ? $_GET["name"] : NULL;
$users = array();
if ($name !== NULL && strlen($name) >= MIN_USERNAME_LENGTH) {
  $users = $db->fetchAll("
     SELECT id, name, ...
     FROM user
     WHERE name LIKE ?
  ", $name);
}

Nechci slyšet, že "je to drobnost, ušetřit jeden SQL dotaz". U malých webů to chápu, ale u těch velkých, kde se hodí ušetřit každá komunikace s databází, se takové kontroly mohou hodit. Děláte je, nebo prostě naperete dotaz rovnou? :D

 
Odpovědět 29.4.2015 0:38
Avatar
Richard
Člen
Avatar
Richard:

strlen() je rychlejší než select -> použít podmínku a neposílat do databáze data zbytečně.
I kdyby (teoreticky) strlen a select měly trvat stejnou dobu, nebo dokonce kdyby strlen byl o něco pomalejší, stejně je vhodnější řešení se vyhnout zbytečné komunikaci s databází.

-> není důvod aby tam nebyla podmínka pokud je výsledek jasný.

Ale platí to samozřejmě pouze pokud nepovoluješ vyhledávání čísti řetězce - chci vyhledat uživatele a vím že měl v nicku aktuální rok, v tom případě jsem v háji.

PS. mb_strlen

Editováno 29.4.2015 2:25
Nahoru Odpovědět  +1 29.4.2015 2:23
$action = $_GET['Life']; | Když dáš mínus, napiš proč!
Avatar
Odpovídá na Richard
Martin Konečný (pavelco1998):

Mně šlo spíše o to, zda takovou podmínku používáš, abys ten dotaz ušetřil. Je mně jasné, že je strlen() rychlejší než komunikace s DB.
Co se týká vyhledání dle části řetězce, pak OK - v tomto příkladu mi šlo o vyhledání dle přesného stringu.

A mb_strlen() nebude třeba, když uživatelské jméno nebude moct mít diakritiku, ale pro příklad jsem nezacházel do detailů :)

 
Nahoru Odpovědět 29.4.2015 9:48
Avatar
Odpovídá na Martin Konečný (pavelco1998)
Dominik Klapuch:

Ahoj,
být tebou, tak bych určitě použil tu podmínku.
Možná trochu z jiného soudku, možná ne, ale to samé dělám i když ověřuji identitu uživatele přes prihlašování. Pokud nesedí velikost hesla, je prázdné nebo podobné nesmysly, tak se nedotazuji ani na databázi a ani s tím už dále nepracuji.

Nahoru Odpovědět 29.4.2015 13:07
Kód a data patří k sobě.
Avatar
Samuel Illo
Redaktor
Avatar
Samuel Illo :

Ak ti ide o rýchlosť, tak jednoznačne použi tú podmienku....
+
nejakú milisekundu získaš tým, že nahradíš strlen isset-om :)

Nahoru Odpovědět  +2 29.4.2015 14:01
www.samuelillo.com; lamka02sk(zavináč)samuelillo.com, www.point.samuelillo.com, www.csgorig.eu
Avatar
Odpovídá na Samuel Illo
Dominik Klapuch:

Jak to myslíš s tím isset? To jsou zcela odlišené funkce a pokud myslíš něco jako isset($name[4]), tak to leda znepřehlední celou podmínku.

Edit: Plus by jsi musel přepsat tu konstantu a znepřehlednil by jsi to ještě víc :)

Editováno 29.4.2015 14:21
Nahoru Odpovědět 29.4.2015 14:19
Kód a data patří k sobě.
Avatar
shaman
Člen
Avatar
Odpovídá na Martin Konečný (pavelco1998)
shaman:

Kazdu globalnu premennu musis validovat. Nikdy nevies co v nej je pretoze prichadza od klienta. Nevies ci je skalarna premenna, pole, objekt, dokonca ci je integer, float alebo string. Vela veci sa moze "nahodou" prihodit. Preto odporucam osetrit kazdu takuto premennu, nezalezi na tom ci ide do SQL alebo ide o rychlost, v prvom rade ide o kvalitny kod, ktory si ty naprogramoval.

Nahoru Odpovědět 29.4.2015 14:56
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Samuel Illo
Redaktor
Avatar
Odpovídá na Dominik Klapuch
Samuel Illo :

Mozno sa to mierne zneprehladni ale isset je vraj az 6-krat rychlejsi (neskusal som). Keby chcel pouzit isset staci hodnotu v konstante prepisat na 4 (to si myslim nie je nic neprehladne) a vlozit ju do issetu. Potom by to vyzeralo nejak takto:

const MIN_USERNAME_LENGTH = 4;

$name = !empty($_GET["name"]) ? $_GET["name"] : NULL;
$users = array();
if ($name !== NULL && !isset($name[MIN_USERNAME_LENGTH])) {
  // ...
}

// Konstantu som nikdy do $something[here] nedaval, tak neviem ci to funguje ale zrejme hej, lebo aj premenne idu....ak nie opravte ma :)

Nahoru Odpovědět 29.4.2015 15:10
www.samuelillo.com; lamka02sk(zavináč)samuelillo.com, www.point.samuelillo.com, www.csgorig.eu
Avatar
Martin Konečný (pavelco1998):

Díky za odpovědi. O rychlost mi nejde, jen čistě o to, zda zacházíte až do detailů validace, nebo tu hodnotu prostě hodíte do DB dotazu a čekáte, co se vrátí :D

 
Nahoru Odpovědět 29.4.2015 15:26
Avatar
Odpovídá na Samuel Illo
Dominik Klapuch:

Je úplně jedno, jak je to rychlé. Pokud se jedná o mikro/nanosekundy, nemá to smysl. Ještě když s tímhle trochu pokazíš návrh - tím myslím to, že kdybych chtěl poté použít strlen namísto isset, musel bych změnit i konstantu a na to se dá hned zapomenout.

Je lepší rychlost nahrabat na algoritmech, nežli na těchto nesmyslech.

Jinak vím, oč ti jde, také při rekurzivním volání metody, která obsahuje is_array používám (array)$pole === $pole, ale moc to smysl nemá :)

Nahoru Odpovědět  ±0 29.4.2015 16:08
Kód a data patří k sobě.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.