Wpis z mikrobloga

Tak mnie ostatnio zastanawia w #laravel dlaczego relacje w ORM wywołują tyle zapytań. Wychodzi na to jakby zapytania były tworzone w pętli. W pracy na co dzień korzystamy z cake i tam też na niektórych podstronach potrafimy mieć po 100 zapytań, gdzie tak naprawdę mamy wywołanie jednej funkcji i podpięcie kilku relacji, potem to wyświetlenie w pętli foreach, ale w pętli nie wrzucamy żadnych zapytań, a przynajmniej ja. :) Kiedyś czytałem, że nie powinno tego się praktykować i ilość zapytań powinna być jak najmniejsza, ale obecne frameworki walą zapytań do bazy danych mnóstwo, więc jak to z tym jest? Już nieaktualne? Już hostingodawcy nie mają limitów zapytań do bazy?

#programowanie #programista15k #php
  • 10
@nophp: Trzeba optymalizować zapytania. Jak masz encję, która ma relacje z innymi obiektami, to w metodach takiego modelu bądź w repozytorium domyślne funkcje pobierają tylko podstawowe dane, bez danych powiązanych. Przekładając to czysty SQL, to po prostu bez "JOIN", a zamiast tego nawet i kilkaset zapytań. Im bardziej złożona struktura tym więcej.

Najlepiej samemu napisać zapytanie przy pomocy jakiegoś QueryBuilder'a, którego zwrotem będą encje zgodnie z ORM. Dobrze napisany kod potrafi
@nophp: chcesz wyświetlić 20 komentarzy na mirko:

SELECT * from mirko_comments
to przemiela ORM na 20 obiektów klasy MirkoComment

ale do każdego komentarza chcesz wyświetlić informacje o autorze

więc w czasie wyświetlania komentarza robisz $mirkoComment->getAuthor()->getGender()
a ORM, w pętli, dla każdego tak wyświetlanego komentarza, robi nowe zapytanie do bazki o autora:

select * from authors where author_id = ?
efekt: 21 zapytań: jedno o komentarze i 20 o autorów

rozwiązanie: do
rozwiązanie: do pierwszego zapytania dokleić autorów JOINem. tak, ORMem też da się.


@MacDada: w #laravel (bo o to pytał autor), a właściwie Eloquent nic nie musisz doklejać joinem. Metoda with() eager loaduje relacje, ale w przeciwieństwie do Dotrine dociąga je osobnym zapytaniem przy udziale whereIn po IDkach kolekcji.
Metoda with() eager loaduje relacje


@nowiutki: pod warunkiem że pobierasz obiekty głównego zapytania wszystkie na raz (za pomocą ->get()), bo jak zrobisz ->cursor() to się te relacje nie załadują
@Ysior: też go kiedyś używałem, ale clockwork lepszy bo możesz debugować również joby w kolejce. Oraz ma plugin pod Firefoxa więc żadnego cssowego/jsowego debugbara nie wciska w kod strony.
Już hostingodawcy nie mają limitów zapytań do bazy?


@nophp: dodatkowe zapytania to zawsze tragedia, które dodają niepotrzebnej roboty i mocno dodają latency do całego zapytania

dlaczego relacje w ORM wywołują tyle zapytań.


@nophp: bo ORMy takie są. Generyczne klocki poskładane w taki sposób, że robią to co maja robić, ale przy użyciu dużej ilości bazowych zapytań, gdzie pisząć takie zapytanie ręcznie możemy je uszyć na miarę