Соединение MySQL, проверяющее каждую строку

#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 по имени пользователя