• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Optymalizacja zapytania sql (Laravel Eloquent)

0 głosów
675 wizyt
pytanie zadane 22 lutego 2021 w SQL, bazy danych przez Bakkit Dyskutant (7,600 p.)
zamknięte 17 marca 2021 przez Bakkit

Cześć, mam mały problem z zapytaniami do bazy danych. Mam nadzieję, że pomożecie mi je zoptymalizować.

Problem polega na tym, że mając w bazie tylko 4 rekordy zużywam aż 18MB RAM na stronie głównej. W przyszłości może dojść do 30-40 wczytywanych rekordów per strona.

Tak wygląda struktura głównej tabeli:

Struktura tabeli relacyjnej (relacja one-to-one):

 

A o to akcja kontrolera strony głównej:

private $COLUMNS = ['id', 'name', 'motd', 'online_status', 'players_online', 'slots', 'version', 'icon'];

    public function __invoke(): View
    {
        $serversPremium = Server::with('data:votes,id')
            ->whereHas('data', function(Builder $query) {
                $query->where('premium', 1)->orderBy('votes', 'desc');
            })
        ->get($this->COLUMNS);

        $servers = Server::with('data:votes,id')
            ->whereHas('data', function(Builder $query) {
                $query->where('premium', 0)->orderBy('votes', 'desc');
            })
        ->paginate(20, $this->COLUMNS);

        return view('index.sections.server.index', [
            'serversPremium' => $serversPremium,
            'servers' => $servers
        ]);
    }

Wszystkie kolumny jakie wyciągam z tabel są wykorzystywane.

 

Rekordy premium i te "nie" premium są wrzucane do osobnych zmiennych, bo w widoku są wyświetlane w osobnych miejscach.

Troszkę w tych zapytaniach jest redundancji, wrzucę tam potem jakiegoś local scope'a, natomiast teraz dla przejrzystości jest to zrobione tak.

komentarz zamknięcia: Rozwiązanie problemu.

3 odpowiedzi

+1 głos
odpowiedź 27 lutego 2021 przez mordimer Mądrala (5,720 p.)
wybrane 17 marca 2021 przez Bakkit
 
Najlepsza
Po co ta relacja 1:1 w tym przypadku ? Pokaż w debugerze laravela co rzeczywiście zjada ta pamiec . Czemu to tak dziwnie wolasz invoke ? Nie podales koniguracji modelu i jak to wolasz po kolei. A jak to jest problem z eloquentem i sobie cos tam za duzo pobiera to pobierz sobie to czystym sqlem.
komentarz 27 lutego 2021 przez Bakkit Dyskutant (7,600 p.)

Po co ta relacja 1:1 w tym przypadku ?

W jednej tabeli są trzymane serwer i ich główne dane a w drugiej ich dane dodatkowe, każdy serwer ma dane główne i dodatkowe czyli każdy z tych rekordów w tabeli głównej ma swój rekord w tabeli relacyjnej. (Jeśli w tabeli głownej zostanie dodany serwer to w tabeli relacyjnej automatycznie zostanie dodany jego rekord z informacjami dodatkowymi).

 

Pokaż w debugerze laravela co rzeczywiście zjada ta pamiec

Co konkretnie pokazać?

 

Czemu to tak dziwnie wolasz invoke ?

Ponieważ to jest Single Action Controller, który zawsze posiada jedną akcje o nazwie __invoke.

 

Nie podales koniguracji modelu i jak to wolasz po kolei.

Nie bardzo rozumiem.

 

A jak to jest problem z eloquentem i sobie cos tam za duzo pobiera to pobierz sobie to czystym sqlem.

Tak wyglądają czyste zapytania, które generuje Eloquent (4):

select `id`, `name`, `motd`, `online_status`, `players_online`, `slots`, `version`, `icon` from `servers` where exists (select * from `servers_data` where `servers`.`id` = `servers_data`.`id` and `premium` = 1)
select `votes`, `id` from `servers_data` where `servers_data`.`id` in (1)
select `id`, `name`, `motd`, `online_status`, `players_online`, `slots`, `version`, `icon` from `servers` where exists (select * from `servers_data` where `servers`.`id` = `servers_data`.`id` and `premium` = 0)
select `votes`, `id` from `servers_data` where `servers_data`.`id` in (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29)

 

Oraz jeszcze ilość zaciąganych modeli:

Data: 29 - Model z bazy relacyjnej

Server: 29 - Model z bazy głównej

komentarz 28 lutego 2021 przez mordimer Mądrala (5,720 p.)

select `id`, `name`, `motd`, `online_status`, `players_online`, `slots`, `version`, `icon` from `servers` where exists (select * from `servers_data` where `servers`.`id` = `servers_data`.`id` and `premium` = 0)
select `votes`, `id` from `servers_data` where `servers_data`.`id` in (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29)

W tych dwóch zapytaniach masz odpowiedź na swoje pytanie. Nie wiem ile masz tam rekordów ale wygląda na to eloquent pod spodem pobiera wszystko i z tego dopiero skleja te dane. Spróbuj zrobić joina do tej drugiej tabeli i wyciągnij również te pola, które potrzebujesz z tej drugiej tabeli cos w tym stylu (w eloquencie sobie juz to napiszesz):

SELECT server.id, server.name i tak dalej ...., servers_data.votes
FROM server
INNER JOIN servers_data ON server.id=servers_data.server_id 
where server_data.premium = 1

A dlatego chciałem konfigurację modelu bo jakoś tą relację "data" zrobiłeś i z ciekawości chciałem ją zobaczyć. Chyba że laravel stał się jeszcze bardziej magiczny i nie trzeba tego teraz robić :D

 

 

 

 

  

0 głosów
odpowiedź 24 lutego 2021 przez Bakkit Dyskutant (7,600 p.)
@ref
0 głosów
odpowiedź 26 lutego 2021 przez Bakkit Dyskutant (7,600 p.)

Kurde chyba nikt nie wiesad

Podobne pytania

0 głosów
1 odpowiedź 414 wizyt
pytanie zadane 8 marca 2021 w PHP przez niezalogowany
0 głosów
0 odpowiedzi 286 wizyt
0 głosów
1 odpowiedź 604 wizyt

93,776 zapytań

142,736 odpowiedzi

323,388 komentarzy

63,381 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...