Jednoduché snížení počtu dotazů na databázi
- Oli
- Člen | 1215
Zdravím,
chtěl bych se zeptat jestli jde nějak jednoduše (bez kešování) snížit
počet dotazů na databázi? Mám to takhle:
$menu = $this->connection->table($this->table)->where(/*podmínka*/);
// Tady nechápu, proč když dám $subMenu = $menu, tak to projde jen jednou a zbytek vubec nevypíše?
$subMenu = $this->connection->table($this->table)->where(/*podmínka*/);
foreach ($menu as $parent)
{
foreach ($subMenu as $child)
{
if ($parent->id == $child->parent_id)
{
dump($child->title);
}
}
}
Problém je, že se ten vnořenej foreach pokaždý ptá až do databáze.
Myslel jsem, že jak je to jednou načtený, tak že to bude brát dotazy
z toho Nette\Database\Table\Selection
u. Že si to uloží a nebude
se ptát databáze.
Někde jsem myslím kdysi četl, že když chci procházet výsledek z databáze vícekrát, že se na to používá nějak fetchAll(). Nevím jestli si to pamatuju dobře, nicméně mi to nefungovalo a ani nevím jestli by to pomohlo…
Díky
- David Matějka
- Moderator | 6445
opravdu to mas takhle? ze v tom vnorenem foreachy vzdycky vypisujes stejny submenu?
jinak, co mas za verzi nette?
- Oli
- Člen | 1215
Jo jo, mám to přesně takhle. Jen to je v šabloně a okolo je html.
;-)
Nette je 2.0.10.
Teda předpokládám, že to šahá pokaždé do db. Když totiž vypustím ten vnitřní foreach, tak padne počet dotazů o $child->title dolů. Ideálně bych použil jednu proměnnou a procházel to takhle:
foreach ($menu as $parent)
{
foreach ($menu as $child)
{
if ($parent->id == $child->parent_id)
{
dump($child->title);
}
}
}
Ale, to ten child provede jen jednou.
- David Matějka
- Moderator | 6445
radsi napis, ceho chces dosahnout, protoze ta podminka ` if ($parent->id == $child->parent_id)` nepekne zavani :) + ukaz strukturu db
- Oli
- Člen | 1215
Z toho jsem měl strach :-D
V db mám zjednodušeně:
id | parent_id | title | slug | text |
1 | NULL | Nadpis | nadpis | bla bla |
2 | 1 | Podnadpis | podnadpis | haha |
3 | NULL | Nadpis 2 | nadpis-2 | bla bla |
4 | 3 | Podnadpis 2 | podnadpis-2 | haha |
5 | 1 | Podnadpis 3 | podnadpis-3 | bla bla |
6 | NULL | Nadpis 3 | nadpis-3 | haha |
Výstup by měl být něco jako:
<ul class="primary_menu">
<li class="parent"><a href="javascript:void(0)">Nadpis 1<i></i></a>
<ul>
<li><a href="#">Podnadpis 1 1</a></li>
<li><a href="#">Podnadpis 1 2</a></li>
</ul>
</li>
<li class="parent"><a href="javascript:void(0)">Nadpis 2<i></i></a>
<ul>
<li><a href="#">Podnadpis 2 1</a></li>
<li><a href="#">Podnadpis 2 2</a></li>
<li><a href="#">Podnadpis 2 3</a></li>
</ul>
</li>
<li><a class="single-line" href="#">Nadpis 3</a></li>
<li><a href="#">Agisoft<br>Nadpis 4</a></li>
</ul>
Editoval Oli (11. 9. 2013 15:06)
- David Matějka
- Moderator | 6445
zkus:
$menu = $this->connection->table('menu')->where('parent_id IS NULL');
foreach($menu as $item) {
foreach($item->related('menu') as $subItem) {
}
}
- Oli
- Člen | 1215
Díky, nepomohlo to, naopak se to zhoršilo ;-) Moje řešení mělo 18 dotazů, tvoje 26. Vizuálně je výsledek stejný.
Pokud by si zapamatovalo nette ten dotaz, tak by bylo jen okolo 5 – 9 dotazu. Nevím přesně, který dotazy to ovlivňuje. Měl jsem 5 a/nebo 9 dotazů, když jsem oddělal vnitřní foreach.
Jiný nápad? :-)
EDIT: S related mám blbý zkušenosti co se týče počtu dotazů. Možná to používám blbě, ale vždycky mnohonásobně vzroste počet dotazů na db…
Editoval Oli (11. 9. 2013 15:31)
- David Matějka
- Moderator | 6445
muzes jeste poslat, jaky dotazy ti to vytvari?
ja to ted zkousel (mam teda 2.1) a zvladlo to ve 2 dotazech..
zkus kdyztak aktualizovat nette na novejsi verzi (2.0.12), jestli tam nebyl nejakej bug..
- Oli
- Člen | 1215
Ted jsem na to prisel. Delal to router. Omlouvam se za v podstatě ztrátu času. :-/ Uplně jsem zapomněl, že si předávám parent_id do odkazu a router, že to převádí… Id jsem změnil na slug, aby mě to nezapočítávalo dotazy pro router, ale na to parent_id jsem zapomnel :-/
Moje řešení má 7 dotazů, tvoje 8. Nevím, kde se tam ten jeden vzal, ale z něj už se nestřílí. Jsou to celkové dotazy na db, nejen na menu.
Díky!