SQL - N+1 problém (N+1 query problem)

SQL - N+1 problém (N+1 query problem)

Co je N+1 problém (N+1 query problem, N+1 performance problem, hrozba N+1). Jedná se o antipattern, kdy se při iterování provádějí další SQL dotazy, což má za následek dodatečnou zátěž na server a to pochopitelně snížuje efektivitu řešení. Zpravidla toto nastává při získávání dat z dalších vazebních tabulek (přes relační vazby).

 

Příklad N+1 problému

Typické pro N+1 problém je kupříkladu tato konstrukce - při iterování kategorií chceme vypsat všechny položky dané kategorie, což má za následek provedené SQL dotazu v každé iteraci.

foreach ($caregories as $category) {
      // do SQL query for each category
      $caretory->getItems();
}

 

Řešení N+1 problému

Obecně lze asi řešení N+1 problému popsat tak, že je třeba se vyvarovat konstrukcím podobným příkladu výše a snažit se relační záznamy načíst rovnou pomocí co nejmenšího počtu SQL dotazů (ideálně jednoho).

 

Řešení N+1 problému v Nette

V Nette za nás N+1 problém řeší databázová vrstva Explorer, kdy se rovnou položí efektivní SQL dotazy,  resp. co nejméně dotazů, na všechny požadované záznamy viz dokumentace k Nette.

 

Řešení N+1 problému v Symfony ORM (Doctrine)

Entitě (Doctrine ORM) s vazbou OneToMany nastavíme fetch na EAGER (Eager loading) takto:

/**
    * @ORM\OneToMany(targetEntity=Items::class, mappedBy="category", fetch="EAGER")
    */
private $items;

Díky tomuto načítání se rovnou načtnou i vazební data. Pokud není fetch specifikován, tak se použije default = LAZY.

 

Další možností je v querybuilderu použít takovouto konstrukci jak praví dokumentace k Symfony:

$this->createQueryBuilder('e')
->innerJoin('e.items', 'i')
->addSelect('i');

Touto konstrukcí se načtou rovnou i všechny vazební záznamy.

 

Jak se ti článek líbil?

Komentáře (0)

Přidat komentář