После очистки запроса, удаления лишних меток и круглых скобок, я считаю, что намного легче следовать следующему и увидеть взаимосвязи между таблицами.Вы хорошо сделали это с помощью соединений leftAlias.leftColumn = rightAlias.rightColumn.
Теперь, когда я могу лучше видеть вещи, давайте рассмотрим ваши таблицы.Они чаще всего выглядят как таблицы поиска, в которых у вас есть идентификатор и описательный столбец, который вы возвращаете.Я бы СОЗДАЛ покрывающие индексы в этих таблицах, чтобы разрешения соединений можно было обрабатывать непосредственно из индексов, а не переходить на страницы необработанных данных.
Одно ДОПОЛНИТЕЛЬНОЕ соображение по времени заключается в добавлении ключевого слова MySQL "STRAIGHT_JOIN", которое сообщаетдвижок для запроса таблиц в том порядке, в котором я их перечислял.Не думай за меня.Каждая из ваших таблиц начинается на самом верхнем уровне и получает все поиски вниз по течению.Вы также можете сравнить время, удалив также предложение STRAIGHT_JOIN. В системе, с которой я работал YEARS назад, потребовалось, чтобы основная таблица с примерно 15M записями и более 20 таблицами поиска зависала после 12+ часов обработки и сокращалась до завершенногозапрос выполняется чуть более часа.
Очистка исходного запроса
SELECT STRAIGHT_JOIN
cou.id AS country_id,
a.id AS area_id,
y.id AS year_id,
su.id AS subject_id,
co1.`name` AS course_name,
ca1.id AS root_category_id,
ca1.`name` AS root_category_name,
ca4.id AS chapter_id,
ca4.`name` AS chapter_name,
ca4.no_of_assets AS no_of_assets,
ca4.active_status AS `status`,
0 AS READ_IT,
0 AS WATCH_IT,
0 AS PLAY_IT,
0 AS PROVE_IT,
count(DISTINCT pa.id) AS APROVE_IT,
if((count(pa.id) > 0),'True', 'False') AS sections_with_content,
count(pa.id) AS content_count,
pa.`status` AS content_flag
FROM
edu_db.category_relation_xref crx1
JOIN edu_db.category ca1
ON crx1.parent_id = ca1.id
LEFT JOIN edu_db.course co1
ON ca1.course_id = co1.id
JOIN edu_db.category_relation_xref crx2
ON crx1.child_id = crx2.parent_id
JOIN edu_db.category ca2
ON crx2.parent_id = ca2.id
JOIN edu_db.category ca3
ON crx2.child_id = ca3.id
JOIN edu_db.category_relation_xref crx3
ON crx2.child_id = crx3.parent_id
JOIN edu_db.category ca4
ON crx3.child_id = ca4.id
JOIN edu_db.course co2
ON ca4.course_id = co2.id
JOIN edu_db.curriculum cu
ON co2.curriculum_id = cu.id
JOIN edu_db.`year` y
ON cu.year_id = y.id
JOIN edu_db.area a
ON y.area_id = a.id
JOIN edu_db.country cou
ON a.country_id = cou.id
JOIN edu_db.subject su
ON cu.subject_id = su.id
LEFT JOIN edu_db.qbnk_category_published_assessment_xref qcpa
ON ca4.id = qcpa.category_id
LEFT JOIN edu_db.qbnk_published_assessment pa
ON qcpa.published_assessment_id = pa.id
LEFT JOIN edu_db.category_relation_xref crx4
ON crx3.child_id = crx4.parent_id
LEFT JOIN edu_db.category ca5
ON crx4.child_id = ca5.id
WHERE
pa.`status` <> 'non_active'
AND qcpa.`status` <> 'deleted'
GROUP BY
ca4.id
Другой элемент ... У вас есть несколько таблиц, которые ЛЕВО соединены, и даже неиспользуется в запросе и может быть полностью удален.Явно "СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ edu_db.category ca5".Вы не извлекаете никаких значений из псевдонима CA5, и левое соединение означает, что вы все равно не заботились об этом.Аналогично для "LEFT JOIN edu_db.category_relation_xref crx4"
SELECT STRAIGHT_JOIN
a.country_id,
a.id AS area_id,
y.id AS year_id,
cu.subject_id,
co1.`name` AS course_name,
ca1.id AS root_category_id,
ca1.`name` AS root_category_name,
ca4.id AS chapter_id,
ca4.`name` AS chapter_name,
ca4.no_of_assets AS no_of_assets,
ca4.active_status AS `status`,
0 AS READ_IT,
0 AS WATCH_IT,
0 AS PLAY_IT,
0 AS PROVE_IT,
count(DISTINCT pa.id) AS APROVE_IT,
if((count(pa.id) > 0),'True', 'False') AS sections_with_content,
count(pa.id) AS content_count,
pa.`status` AS content_flag
FROM
edu_db.category_relation_xref crx1
JOIN edu_db.category ca1
ON crx1.parent_id = ca1.id
LEFT JOIN edu_db.course co1
ON ca1.course_id = co1.id
JOIN edu_db.category_relation_xref crx2
ON crx1.child_id = crx2.parent_id
JOIN edu_db.category_relation_xref crx3
ON crx2.child_id = crx3.parent_id
JOIN edu_db.category ca4
ON crx3.child_id = ca4.id
JOIN edu_db.course co2
ON ca4.course_id = co2.id
JOIN edu_db.curriculum cu
ON co2.curriculum_id = cu.id
JOIN edu_db.`year` y
ON cu.year_id = y.id
JOIN edu_db.area a
ON y.area_id = a.id
JOIN edu_db.qbnk_category_published_assessment_xref qcpa
ON ca4.id = qcpa.category_id
AND qcpa.`status` <> 'deleted'
JOIN edu_db.qbnk_published_assessment pa
ON qcpa.published_assessment_id = pa.id
AND pa.`status` <> 'non_active'
GROUP BY
ca4.id
Ваши предложения WHERE, связанные с "pa" и "qcpa", отменяют часть LEFT JOIN, поскольку where превращает ее в предложение WHERE.Поэтому я удалил компонент «ВЛЕВО» И переместил часть предложения where непосредственно в этот компонент соединения.
Вы тянете «предметную» таблицу (псевдоним su), но только захватывает su.id.Поскольку у вас есть идентификатор субъекта из псевдонима «cu», вы можете просто использовать вместо него «cu.subject_id» и удалить еще одну таблицу из запроса - ЕСЛИ вы не планируете получать другие описания из таблицы «субъект».Это, вероятно, то же самое для вашей страны, области, года присоединения, а также.Если у вас уже есть идентификатор из предыдущей таблицы, используйте его и отбросьте ненужное ...
Не используйте псевдонимы "ca2" или "ca3" для каких-либо дополнительных подробностей, описаний, избавьтесь отэто.
Так что мои предложения по индексам для каждой таблицы будут включать следующее.Это будет больше ПОКРЫТИЯ индексов.Это не должны быть отдельные индексы в одной и той же таблице, такие как индекс Tbl1 для идентификатора, индекс Tbl1 для описания, но индекс Tbl1 ON (идентификатор, описание) в качестве одного индекса.
table index
qbnk_published_assessment ( id, `status` )
qbnk_category_published_assessment_xref ( category_id, `status`, published_assessment_id )
area ( id )
`year` ( id, area_id )
curriculum ( id, year_id )
course ( id, curriculum_id )
category ( id, course_id )
category_relation_xref ( parent_id, child_id )