kdyby/doctrine trvání dotazů
- jarda256
- Člen | 130
Ahoj, chtěl bych se zeptat. Mám Entitu Event a provádím nad ní pomocí EventFacade tvorbu nové a editaci, ale přijde mi divné, že by tvorba spustila 3 queries, které by trvali 96ms a editace 4 které 110ms. Moc se v tom nevyznám, takže netuším co by mohlo způsobit, že to trvá tak dlouho (popřípadě je to dlouho nebo si to jen myslím). Předem díky za opověď.
<?php
namespace App\Model\Facades;
use App\Model\Entities\Event;
use Nette\Utils\ArrayHash;
use Nette\Object;
/**
* @package App\Model\Facades
*/
class EventFacade extends BaseFacade
{
/**
* @param int|NULL $id
* @return Event|NULL
*/
public function getEvent($id)
{
return isset($id) ? $this->em->find(Event::class, $id) : NULL;
}
/**
* @param ArrayHash $data
*/
public function createEvent($data)
{
$element = new Event();
$element->visible = $data->visible;
$element->name = $data->name;
$element->ename = $data->ename;
$element->date = $data->date;
$element->regInt1 = $data->regInt1;
$element->regInt2 = $data->regInt2;
$element->regInt3 = $data->regInt3;
$element->regInt4 = $data->regInt4;
$element->regInt5 = $data->regInt5;
$element->approve = $data->approve;
$element->regCars = $data->regCars;
$element->optionalItems = $data->optionalItems;
$element->note = $data->note;
$this->em->persist($element);
$this->em->flush();
}
/**
* @return Event[]
*/
public function getAllEvents()
{
$qb = $this->em->createQueryBuilder();
$qb->addSelect('partial e.{id,visible,name,date,approve,regCars,optionalItems,note}')
->from(Event::class,'e')
->orderBy('e.date','DESC');
$query = $qb->getQuery();
$query->useQueryCache(true);
$result = $query->getResult();
return $result;
}
/**
* @param int $id
* @param ArrayHash $data
*/
public function editEvent($id,$data)
{
$element = $this->getEvent($id);
$element->visible = $data->visible;
$element->name = $data->name;
$element->ename = $data->ename;
$element->date = $data->date;
$element->regInt1 = $data->regInt1;
$element->regInt2 = $data->regInt2;
$element->regInt3 = $data->regInt3;
$element->regInt4 = $data->regInt4;
$element->regInt5 = $data->regInt5;
$element->approve = $data->approve;
$element->regCars = $data->regCars;
$element->optionalItems = $data->optionalItems;
$element->note = $data->note;
$this->em->flush();
}
}
<?php
namespace App\Modules\Admin\Presenters;
use Nette;
use App\Model;
use App\Forms;
use Nette\Forms\Container;
use App\Presenters\BaseAdminPresenter;
use Zend\Hydrator;
class EventPresenter extends BaseAdminPresenter
{
/** @var Forms\CreateEventFormFactory @inject */
public $createEventFactory;
/** @var Forms\EditEventFormFactory @inject */
public $editEventFactory;
/** @var Model\Facades\EventFacade @inject */
public $eventFacade;
private $events;
public function renderDefault()
{
}
public function actionShow()
{
$this->events = $this->eventFacade->getAllEvents();
}
public function renderShow()
{
$this->template->events = $this->events;
}
public function actionEdit($id = NULL)
{
$event = $this->eventFacade->getEvent($id);
if ($event !== NULL)
{
$hydrator = new Hydrator\ArraySerializable();
$event = $hydrator->extract($event);
$this["editEventForm"]->setDefaults($event);
}
}
protected function createComponentEditEventForm()
{
return $this->editEventFactory->create(function () {
$this->flashMessage("Akce byla úspěšně upravena", 'success');
$this->redirect(':Admin:Event:show');
});
}
protected function createComponentCreateEventForm()
{
return $this->createEventFactory->create(function () {
$this->flashMessage("Akce byla úspěšně vytvořena", 'success');
$this->redirect(':Admin:Event:show');
});
}
}
- jarda256
- Člen | 130
S tím nemám problém to vidím. Jen tomu úplně nerozumím. Výpis všech eventů třeba spustí klasický select, který trvá podle tracy 3.5 ms ale v admineru trvá ani ne 1ms. Editace spustí samozřejmě načtení toho konkrétního prvku který edituji 2.8ms. Poté „START TRANSACTION“ 3.4ms pak klasický update 20.48 ms a pak „COMMIT“ a poslední 3 tedy referují k $this->em->flush(); ve funkci edit event. Nevím jestli je to tak normální tudíž i ta doba je ok nebo jestli mám tedy něco špatně.
- leninzprahy
- Člen | 150
To, že stejný dotaz jednou trvá 4 ms a jindy 1 ms, je u MySQL celkem normální, hodně záleží, jak je tam nastaveno kešování. Většinou první dotaz trvá déle, pak už to jde rychleji.
Ukládání v transakci je u Doctrine výchozí chování. Když zavoláš
$em->flush();
, propočítá se seznam změn a ty se v transakci
synchronizují do databáze, viz http://docs.doctrine-project.org/…objects.html#…
Mě osobně ty časy připadají v pohodě, pokud bych chtěl optimalizovat, tak spíše nastavením databáze…
- leninzprahy
- Člen | 150
hitzoR napsal(a):
Mi ty časy vpohodě moc nepřijdou, průměrný dotaz v mojí aplikaci trvá něco mezi 0.2 a 0.4 ms. 20 ms je strašně moc.
Obávám se, že nejde obecně říct, že 0.2, 2 nebo 20 ms je moc nebo málo. Záleží na hrozně moc okolnostech, od železa, přes databázový server a jeho nastavení, schéma databáze až po samotné dotazy.
Omlouvám se, ale spojení „průměrný dotaz“ je takové nic neříkající, třeba jako průměrná jízda autem, je 20 minut moc nebo málo? :)
Na druhou stranu, použití Doctrine bude vždycky pomalejší a na prostředky náročnější, než čisté SQL. Je to prostě daň za odstínění a abstrakci (podobně jako kód v php bude pomalejší než kód v C, nebo assembleru).
- hitzoR
- Člen | 51
Jan Mikeš napsal(a):
@hitzoR záleží na stroji, na databázi, na typu dotazu, zmínil, že se jedná o UPDATE, ty trvají trochu déle, obyč selecty jsou u mě také pod 1ms, u updatů je to více.
leninzprahy napsal(a):
Obávám se, že nejde obecně říct, že 0.2, 2 nebo 20 ms je moc nebo málo. Záleží na hrozně moc okolnostech, od železa, přes databázový server a jeho nastavení, schéma databáze až po samotné dotazy.
Tak je jasné, že na stroji záleží, ale na žádném ze zhruba desíti serverů, které mi prošly pod rukama za dobu, co v dělám v Nette, mi nešel ani jeden dotaz (včetně updatů a insertů do tabulek s hromadou klíčů a constraintů) nějak drasticky přes 2 ms.
leninzprahy napsal(a):
Na druhou stranu, použití Doctrine bude vždycky pomalejší a na prostředky náročnější, než čisté SQL. Je to prostě daň za odstínění a abstrakci (podobně jako kód v php bude pomalejší než kód v C, nebo assembleru).
Je jasné, že Doctrine aplikaci trochu zpomalí, ale na query execution time to nemá absolutně vliv, to je čistě v režii MySQL serveru. Jedině že by Doctrine do debug panelu nevypisovala čistý čas trvání query + režie (jako to dělá Nextras\Orm nebo NDB), ale přidávala k tomu třeba i čas namapování na entity a dalšího zpracování.
- Jiří Nápravník
- Člen | 710
Já si dovolím jednu otázku k Doctrine. Nevíte jak jde zavolat flush, ale tak aby to neběželo v transakci? Konkrétní příklad, na frontendu zapisuji otevření článku, a je mi opravdu jedno, že to neproběhne v transakci, přijde mi to i zbytečně pomalé přes to. Stačil by klasický insert mimo transakci. Jde to nějak vynutit v doctrine? Nebo musím přímo přes query nad DBAL?