Использование SELECT в SELECT в запросе MySQL - PullRequest
4 голосов
/ 21 декабря 2011

Обычно используется SELECT в пределах SELECT для уменьшения количества запросов; но, как я уже исследовал, это приводит к медленному запросу (что, очевидно, вредно для производительности MySQL). У меня был простой запрос как

SELECT something
 FROM posts
 WHERE id IN (
  SELECT tag_map.id
  FROM tag_map
  INNER JOIN tags
  ON tags.tag_id=tag_map.tag_id
  WHERE tag IN ('tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6')
  )

Это приводит к медленным запросам: «время запроса 3-4 с; время блокировки около 0,000090 с; проверено около 200 строк».

Если я разделю SELECT запросов, каждый из них будет довольно быстрым; но это увеличит количество запросов, что не очень хорошо при высоком параллелизме.

Это обычная ситуация или что-то не так с моим кодированием?

Ответы [ 3 ]

13 голосов
/ 21 декабря 2011

В MySQL выполнение такого подзапроса является «коррелированным запросом».Это означает, что результаты внешнего SELECT зависят от результата внутреннего SELECT.В результате ваш внутренний запрос выполняется один раз в строке, что очень медленно.

Вы должны реорганизовать этот запрос;присоединиться ли вам дважды или использовать два запроса в большинстве случаев не имеет значения.Двойное соединение даст вам:

SELECT something
FROM posts
INNER JOIN tag_map ON tag_map.id = posts.id
INNER JOIN tags ON tags.tag_id = tag_map.tag_id
WHERE tags.tag IN ('tag1', ...)

Для получения дополнительной информации см. Руководство MySQL по преобразованию подзапросов в JOIN .

Совет: EXPLAIN SELECT покажет вам, какоптимизатор планирует обработку вашего запроса.Если вы видите DEPENDENT SUBQUERY, вам следует выполнить рефакторинг, это мегамедленнее.

2 голосов
/ 21 декабря 2011

Вы можете улучшить его, используя следующее:

SELECT something
FROM posts
INNER JOIN tag_map ON tag_map.id = posts.id
INNER JOIN tags
ON tags.tag_id=tag_map.tag_id
WHERE <tablename>.tag IN ('tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6')

Просто убедитесь, что вы выбираете только то, что вам нужно, и не используете *;также укажите, в какой таблице у вас есть столбец тега, чтобы вы могли заменить

1 голос
/ 21 декабря 2011

Join выполняет фильтрацию результатов.При первом соединении будут сохраняться результаты с выполнением условия 1-го включения, а затем условие 2-го дает окончательный результат при условии 2-го включения.

SELECT something
FROM posts
INNER JOIN tag_map ON tag_map.id = posts.id
INNER JOIN tags ON tags.tag_id = tag_map.tag_id AND tags.tag IN ('tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6');

Вы можете увидеть эти обсуждения переполнения стека:

question1 question2

Объединение помогает уменьшить временную сложность и повышает стабильность работы сервера.

Информация для преобразования подзапросов в объединения:

link1 link2 link3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...