#mysql #join
#mysql #Присоединиться
Вопрос:
Выполнение этого запроса на моем сайте занимает очень много времени. У меня есть блог и форум на моем сайте, которые я свободно интегрировал, поэтому у каждой учетной записи форума есть учетная запись в блоге, и наоборот. Однако идентификаторы user_id в каждой таблице не коррелированы, поэтому я объединял их по имени пользователя.
SELECT *
FROM comments AS c
INNER JOIN articles AS a ON c.article_id = a.article_id
INNER JOIN user_profiles AS p ON c.user_id = p.user_id
INNER JOIN blog_users AS b ON c.user_id = b.user_id
INNER JOIN forum_users AS f ON b.username = f.username
WHERE a.article_id = :article_id
ORDER BY c.comment_id DESC
LIMIT 0 , 30
Когда я использовал explain в запросе, я увидел, что последнее соединение проверяло каждую отдельную строку в таблице forum_users, чтобы получить результат, который составляет более 1 000 000 строк. Столбцы username для обеих таблиц проиндексированы, и все таблицы имеют формат InnoDB. В качестве обходного пути я сохраняю user_id форума каждого пользователя в таблице blog_users, и наоборот, чтобы я мог присоединиться непосредственно к user_id, запрос которого выполняется намного быстрее, но я хотел бы избежать необходимости делать это, если это возможно. Есть ли способ, которым я мог бы переработать запрос, чтобы соединение с именем пользователя было более эффективным?
Комментарии:
1. Можете ли вы выполнить
EXPLAIN EXTENDED
этот запрос и опубликовать результат?
Ответ №1:
Совпадают ли наборы символов таблицы и столбца? Например, blog_users в utf8 и forum_users в latin1? Если они не совпадают, mysql не будет использовать индексы. Вы можете изменить набор символов с помощью, например:
ALTER TABLE blog_users CONVERT TO CHARACTER SET utf8
Если это проблема, внимательно прочитайте документы, прежде чем делать это. Это может изменить содержимое столбцов. http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
Комментарии:
1. Вы были абсолютно правы. MySQL запускал CONVERT() для таблицы с 5 000 000 строками при каждом запросе, из-за чего запрос выполнялся вечно. Изменение обеих кодировок на одну и ту же исправило проблему.
Ответ №2:
Две вещи… Есть ли в вашей таблице комментариев индекс по идентификатору статьи … если нет, получите его… Во-вторых, ваше предложение where ссылается на ОБЪЕДИНЕННУЮ таблицу запроса, а не на основную таблицу в вашем SELECT FROM … Поскольку у них обоих есть столбцы для идентификатора статьи, я бы изменил ваше предложение where на
WHERE c.Article_ID = :article_ID
Кроме того, убедитесь, что индексы на
user_profiles индексирует по User_ID
blog_users индексирует по User_ID
индекс forum_users по имени пользователя