У меня есть запрос, который выбирает таблицу узлов, а затем присоединяет к ней таблицу заголовков.Для этого сначала необходимо объединить промежуточную таблицу идентификаторов узлов и идентификаторов заголовков, что позволяет установить связь «многие ко многим» между первыми двумя таблицами.Оба соединения являются внутренними, поэтому выбираются только узлы с правильно настроенным и существующим заголовком.Я считаю, что все это должно быть чисто и эффективно - проблема заключается в следующем:
Существует также четвертая таблица, которая обеспечивает простую иерархию для узлов;node_parents.Каждая строка имеет два поля;идентификатор узла и идентификатор узла, который действует как родитель этого узла (node_id и parent_id).Некоторые узлы не имеют дочерних элементов, настроенных в этой базе данных (т. Е. Сам узел не помечен как родительский в какой-либо строке таблицы node_parents) - это узлы, которые я пытаюсь выбрать.
Дополнительным критерием для этих бездетных узлов является то, что у них настроен определенный заголовок - отсюда подзапрос, который сначала выбирается из node_titles, а затем во внутреннем соединении node_parents.У подзапроса также есть GROUP BY, потому что некоторые узлы являются родителями нескольких узлов, поэтому их node_id будет излишне появляться в результатах несколько раз.Следует также отметить, что из-за этого первичный ключ для node_parents представляет собой комбинацию node_id и parent_id.
Запрос:
SELECT `nodes`.`node_id`,
`titles`.`title`
FROM `nodes`
INNER JOIN `node_titles`
ON `nodes`.`node_id` = `node_titles`.`node_id`
INNER JOIN `titles`
ON `node_titles`.`title_id` = `titles`.`title_id`
WHERE `nodes`.`node_id` NOT IN
(
SELECT `node_titles`.`node_id`
FROM `node_titles`
INNER JOIN `node_parents`
ON `node_titles`.`node_id` = `node_parents`.`parent_id`
WHERE `node_titles`.`title_id` = 1
GROUP BY `node_titles`.`node_id`
)
AND `titles`.`title_id` = 1
Размеры таблиц: node = ~ 32 000 node_titles =~ 49 000 заголовков = 3 node_parents = ~ 55 000
Выполнение запроса занимает около 16 минут.Кто-нибудь может предоставить какие-либо указатели?Я попытался профилировать запрос - который не имеет длительных зависаний, но он повторяет этот цикл для каждой выбранной строки:
| executing | 0.000005 |
| Copying to tmp table | 0.515815 |
| Sorting result | 0.000053 |
| Sending data | 0.000028 |
Я также пытался отключить подзапрос и использовать LEFT.ПРИСОЕДИНЯЙТЕСЬ к WHERE, foo НЕ НУЛЬ, но это все еще занимает много времени для обработки - профилировщик требует ~ 180 секунд для 'Копирования в таблицу tmp'.
В конечном счете, я подозреваю, что это может быть проблема с индексированием - ноВ любом случае, я был бы признателен за ответы, которые не ставят под сомнение реализацию запроса, если только они не преследуют возможную причину замедления (например, да, заголовки и узлы должны находиться в отношениях «многие ко многим»).Спасибо всем, и дополнительную информацию по запросу!