2012-06-13 4 views
0

Любые советы о том, как я могу заставить этот запрос работать быстрее?Проблемы с mysql speed

SELECT *, p.* 
FROM grouped g 
INNER JOIN form p 
on p.id = g.id 

LEFT JOIN prospect ps 
ON (p.appphone = phone_bus OR p.appphone = phone_res OR p.appphone = phone_fax) AND p.appphone != '' 
WHERE p.agname like '%test%' 
ORDER BY p.agname DESC 
limit 0, 100 

Если я изменяю ON, чтобы не использовать ИЛИ он работает быстро. Как это занимает 30-40 секунд.

p.appphone, phone_bus, phone_res, phone_fax и p.agname индексируются в таблице.

+0

Сколько строк в таблицах, которые вы запрашиваете? –

+0

@brian 80,000 in p, 60,000 in ps и 80,000 in g – user583576

+0

Спасибо. Где находится этот db? –

ответ

0

Вы выполняете внутреннее соединение, которое должно идти быстро, если оно правильно проиндексировано, левое соединение в матче «% test%», вероятно, находится там, где оно занимает время.

он проходит через ваши max 60k строк (вы выбираете все столбцы), и когда он попадает в поле agname, он должен пересекать строку, чтобы соответствовать тесту слова где-то в строке 60 000 раз. Я бы сказал, оптимизировать «% тестовое%», если есть ни в коем случае вокруг этого ... Вы можете

appphone - сколько различных сценариев есть -

ON (**p.appphone = phone_bus OR p.appphone = phone_res OR p.appphone = phone_fax**) AND p.appphone != '' 

вы могли бы присоединиться на ключ, и затем используйте свой вложенный оператор OR в предложении WHERE, нет?

Возможно, вы можете сказать, где p.appphone <> phone_print или что-то такое, что будет включать этот вложенный оператор OR, но оптимизирует его, поэтому он просто ищет то, что не является, а не тремя разными экземплярами того, что могло бы быть. также действительно p.appphone действительно = '', или это null? Не уверен точно, насколько быстрее он это сделает, но вы можете сказать, где p.appphone не является нулевым слева, как упоминалось ранее.

+0

, если я выберу OR в операторе ON, он работает быстро. мне нужно искать во всех этих случаях в ON. – user583576

+0

Тогда, к сожалению, я думаю, что это займет некоторое время, если вы не создадите таблицу для размещения результатов внутреннего соединения, а затем оставите соединение на этом, иначе это будет большой проблемой для бэкэнд mySQL. Вы пробовали только индексирование на agname и appphone? – Hituptony

0

Я бы попробовал:

  1. Использование ANY оператора;
  2. перемещение p.appphonne != '' в пункт WHERE;
  3. точное SELECT список, 'cos * уже содержит поля p.*.

Пожалуйста, попробуйте этот запрос:

SELECT *, p.* 
    FROM grouped g 
    JOIN form p ON p.id = g.id 
    LEFT JOIN prospect ps 
    ON p.appphone = ANY(ps.phone_bus, ps.phone_res, ps.phone_fax) 
WHERE p.agname LIKE '%test%' 
    AND p.appphone != '' 
ORDER BY p.agname DESC 
LIMIT 0, 100; 

Пожалуйста, включите EXPLAIN результат запроса в вашем первом сообщении.