MySQL запрос занимает много времени.Я пробовал много вариантов запроса, и, похоже, ничто не влияет на скорость - PullRequest
1 голос
/ 27 февраля 2012

Вот мой запрос в его нынешнем виде и структура данных:

   SELECT * 
     FROM gmm_sql as a
LEFT JOIN usds as b ON a.dp_id = b.dp_id
LEFT JOIN usdsown as c ON b.dp_id = c.dp_id 
    WHERE a.comm like '%tree%'
  • gmm_sql: 21 полей. Все поля varchar () смешаны с 20 - 255. 4882 записей.
  • usds: 7 полей. Все поля varchar () смешаны с 20 - 255. 304 713 записей.
  • usdsown: 14 полей. Все поля varchar () смешаны с 20 - 255. 107 606 записей.

Я подтвердил, что есть совпадения вручную. Я использую MySQL Workbench для запуска этих тестов запросов. Запрос просто продолжает работать в течение 10 минут и не останавливается ...

Я что-то серьезно не так делаю?

Вот вывод EXPLAIN:

id  select_type table   type    possible_keys   key key_len ref rows    Extra 
1   SIMPLE  a   ALL NULL    NULL    NULL    NULL    3973    Using where
1   SIMPLE  b   ALL dp_id   NULL    NULL    NULL    304345  
1   SIMPLE  c   ALL NULL    NULL    NULL    NULL    105711  

Ответы [ 3 ]

3 голосов
/ 27 февраля 2012

Предполагая, что поля id проиндексированы, это все еще потенциально огромный набор данных. Затем у вас есть последнее предложение where для varchar с подстановочными знаками ... это приведет к полному сканированию таблицы всего набора результатов и сведет на нет любой индекс в поле a.comm.

Просто любопытно, но вы можете проверить это, изменив select * на «select count (a.comm)» и отбросьте предложение where. Если это все еще занимает вечность, это предложение where, в противном случае это построение набора результатов.

2 голосов
/ 27 февраля 2012

Первая точка зрения, которую я вижу:

WHERE a.comm like '%tree%'

Даже если у вас есть индекс на GMM_SQL.comm, подстановочный знак в левой части строки делает индекс бесполезным. Хотя это работает, это буквально худший способ поиска контента, тип данных которого связан со строками.

Полнотекстовый поиск ( ссылка на MySQL ) является предпочтительным методом поиска содержимого в строке. Но IIRC, MySQL все еще требует, чтобы таблица была MyISAM ...

Следующий пункт:

SELECT *

Возвращает все столбцы из всех таблиц, которые являются JOIN'd. Предложение SELECT должно содержать только те столбцы, которые действительно необходимы, потому что:

  1. Вы возвращаете больше данных, чем нужно
  2. Тип данных может сильно повлиять на производительность - IE: если один из столбцов - очень длинная строка или двоичные / BLOB-данные

В-третьих, ваши критерии JOIN. Чем меньше тип данных, тем быстрее выполняется запрос. Я собираюсь предположить что-нибудь с id подразумевает INT. Не используйте BIGINT, если вам это не нужно.

2 голосов
/ 27 февраля 2012

Make FULLTEXT index для gmm_sql.gmm. + Убедитесь, что все внешние ключи проиндексированы.

WHERE a.comm like '%tree%' - самая дорогая операция с вашими данными. Вы должны буквально выполнить полное сканирование таблицы. Обычного индекса недостаточно, потому что у вас есть подстановочный знак в начале последовательности совпадений.

Кроме того, вы можете использовать lucene или sphynx , если ваша база данных не поддерживает этот тип индекса.

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