Powinieneś uprościć swoje zapytanie. To skróciłoby trochę czasu egzekucji. Nie mogę przetestować twojego zapytania, ale oto kilka wskazówek:
- nie sortuj podczas wykonywania count()
- możesz sortować według orderBy('p.id', 'DESC') , zostanie użyty indeks
- zamiast leftJoin() możesz użyć join() jeśli przynajmniej jeden rekord zawsze istnieje w połączonej tabeli. W przeciwnym razie ten rekord zostanie pominięty.
- KNP/Paginator używa DISTINCT() do odczytywania tylko odrębnych rekordów, ale może to prowadzić do używania tablicy disk tmp
- $query->getArrayResult() używa trybu ukrywania tablicy, który zwraca tablicę wielowymiarową i jest znacznie szybszy niż ukrywanie obiektów dla dużego zestawu wyników
- możesz użyć częściowego select('częściowy p.{id, inne używane pola}') , w ten sposób załadujesz tylko potrzebne pola, możesz pominąć niepotrzebne relacje podczas korzystania z hydratacji obiektu
- sprawdź SF profiler EXPLAIN dla danego zapytania w sekcji doktryny, być może indeksy nie są używane
- czy p.hashtags i p.likes zwracają tylko jeden wiersz czy to oneToMany, co mnoży wynik
- może jakieś zmiany w projekcie postów, które usunęłyby niektóre połączenia:
- mieć pole p.hashtags zdefiniowane jako @ORM\Column(type="array") i mają zapisane wartości ciągów tagów. Później może użyć wyszukiwania pełnotekstowego w zserializowanej tablicy.
- mieć pole p.likesCount zdefiniowane jako @ORM\Column(type="integer") który miałby liczbę polubień
Używam KnpLabs/KnpPaginatorBundle a także mogą mieć problemy z szybkością w przypadku złożonych zapytań.
Zwykle użycie LIMIT x,z jest powolne dla DB, ponieważ uruchamia COUNT na całym zbiorze danych. Jeśli indeksy nie są używane, jest to boleśnie powolne.
Możesz użyć innego podejścia i zrobić niestandardową paginację, korzystając z ID, ale to skomplikowałoby twoje podejście. Użyłem tego z dużymi zestawami danych, takimi jak tabele SYSLOG. Ale tracisz funkcję sortowania i całkowitej liczby rekordów.