Трябва да опростите заявката си. Това би съкратило известно време за изпълнение. Не мога да тествам вашата заявка, но ето няколко насоки:
- не правете сортиране, докато изпълнявате count()
- можете да сортирате по orderBy('p.id', 'DESC') , ще се използва индекс
- вместо leftJoin() можете да използвате join() ако поне един запис винаги съществува в обединена таблица. В противен случай записът се пропуска.
- KNP/Paginator използва DISTINCT() за четене само на отделни записи, но това може да доведе до използване на дискова tmp таблица
- $query->getArrayResult() използва режим на хидратиране на масиви, който връща многоизмерен масив и е много по-бърз от хидратирането на обекти за голям набор от резултати.
- можете да използвате частичен select('partial p.{id, other used fields}') , по този начин ще заредите само необходимите полета, може би ще пропуснете ненужните връзки, когато използвате хидратация на обект
- проверете SF profiler EXPLAIN за дадена заявка в раздел доктрина, може би не се използват индекси
- p.hashtags и p.likes връщат ли само един ред или е oneToMany, което умножава резултата
- може би някои промени в дизайна на публикациите, които биха премахнали някои съединения:
- да имат поле p.hashtags, дефинирано като @ORM\Column(type="array") и имат съхранени низови стойности на тагове. По-късно може би използвайки пълнотекстово търсене в сериализиран масив.
- да имат поле p.likesCount, дефинирано като @ORM\Column(type="integer") което би имало брой харесвания
Използвам KnpLabs/KnpPaginatorBundle и може да има проблеми със скоростта за сложни заявки.
Обикновено използването на LIMIT x,z е бавно за DB, защото изпълнява COUNT върху целия набор от данни. Ако не се използват индекси, това е болезнено бавно.
Можете да използвате различен подход и да направите някои персонализирани пагинации чрез напредване на ID, но това би усложнило вашия подход. Използвах това с големи набори от данни като SYSLOG таблици. Но губите функцията за сортиране и общ брой записи.