Неправильное решение: запросы со многими объединениями одновременно должны всегда выполняться быстрее, чем использование фрагментированных запросов в нескольких операторах SQL, при условии, что ваш запрос правильный.
Если ваш запрос ужасно медленный, как только вы добавляете n: n или 1: n объединений, в Doctrine есть несколько причин для этого.
Одной из наиболее частых ошибок в запросах с несколькими объединениями является использование конструкции LEFT JOIN + WHERE, в которой вы можете использовать INNER JOIN с ON. Рассмотрим пример DQL:
SELECT a.*, c.*
FROM Article a
LEFT JOIN a.Buyer b
LEFT JOIN b.Creditcard c
LEFT JOIN c.digitalinfo d
WHERE b.id = 2 AND d.info LIKE 'TEST%'
Это очень медленный запрос, если во всех таблицах 10000 записей. Сначала она объединит всю таблицу b с таблицей a, что приведет к 10000 ^ 2 строкам, тогда как в предложении WHERE вы отбрасываете почти 99,9% из них всех.
SELECT a.*, c.*
FROM Article a
INNER JOIN a.Buyer b WITH b.id=2
LEFT JOIN b.Creditcard c
INNER JOIN c.Digitalinfo d WITH d.info LIKE 'TEST%'
Здесь ВНУТРЕННЕЕ СОЕДИНЕНИЕ a.Buyer b не заканчивается 100 000 000 строк, но, поскольку оно использует расширенное предложение ON (Doctrine называет это WITH), оно оставляет только небольшой набор. Поэтому два других соединения будут молниеносными по сравнению с тем, что они выполняли, как в другом утверждении.
Также убедитесь, что у вас ВСЕГДА есть индексы
- В столбцах, по которым вы ведете поиск. (Если вы выполняете поиск по полному имени, как в FirstName + '' + LastName, создайте индекс для этой последовательности!)
- В столбцах, для которых вы выполняете определенные объединения
- Для внешних ключей и полей, для которых установлена ссылка.
Если вы хотите узнать, что ваша база данных делает за кулисами, вы можете, например, ввести в MySQL тип EXPLAIN
, за которым следует ваш запрос, и он точно скажет вам, почему это занимает так много времени.