2013-11-27 3 views
2

У меня есть следующий запрос, который занимает очень много времени для выполнения. Мне нужно ускорить его, но я теряю информацию о том, какую технику использовать. Это запрос:Оптимизация Mysql на основе объяснения

SELECT 
    `User`.`id`, 
    `User`.`username`, 
    `User`.`password`, 
    `User`.`role`, 
    `User`.`created`, 
    `User`.`modified`, 
    `User`.`email`, 
    `User`.`other_user_id`, 
    `User`.`first_name`, 
    `User`.`last_name`, 
    `User`.`place_id`, 
    `Resume`.`id`, 
    `Resume`.`user_id`, 
    `Resume`.`other_resume_id`, 
    `Resume`.`other_user_id`, 
    `Resume`.`file_extension`, 
    `Resume`.`created`, 
    `Resume`.`modified`, 
    `Resume`.`is_deleted`, 
    `Resume`.`has_file`, 
    `Resume`.`is_stamped`, 
    `Resume`.`is_active` 
FROM 
    `streetofwalls`.`users` AS `User` 
    LEFT JOIN `my_database`.`attempts` AS `Attempt` 
     ON (`Attempt`.`user_id` = `User`.`id` AND `Attempt`.`test_id` != 5) 
    LEFT JOIN `my_database`.`reports` AS `Resume` 
     ON (`Resume`.`user_id` = `User`.`id`) 
WHERE 
    `Attempt`.`test_id` = 8 
    AND `Attempt`.`score` > 60 
    AND `User`.`id` IN (
     SELECT 
      `User1`.`id` 
     FROM 
      `my_database`.`users` AS User1 
      LEFT JOIN `my_database`.`tags_users` AS TagUser 
       ON (`User1`.`id`= `TagUser`.`user_id`) 
      LEFT JOIN `my_database`.`tags` AS Tag 
       ON (`TagUser`.`tag_id`= `Tag`.`id`) 
     WHERE `Tag`.`id` = (8)) 
    AND `User`.`id` NOT IN (
     SELECT 
      `User1`.`id` 
     FROM 
      `my_database`.`users` AS User1 
      LEFT JOIN `my_database`.`tags_users` AS TagUser 
       ON (`User1`.`id`= `TagUser`.`user_id`) 
      LEFT JOIN `my_database`.`tags` AS Tag 
       ON (`TagUser`.`tag_id`= `Tag`.`id`) 
     WHERE `Tag`.`id` = (3)) 
    AND `Resume`.`has_file` = 1 
GROUP BY `User`.`id` 
ORDER BY `Attempt`.`score` DESC; 

Этот запрос генерирует следующие объяснения: explain for the above query

Как вы можете видеть, у меня есть несколько индексов по этому запросу. На данный момент только таблица резюме не может быть проиндексирована. Можно ли индексировать эту таблицу в контексте этого запроса? Есть ли другой способ ускорить этот запрос, о котором я не думал? Его непозволительно медленно для его намеченной функции, и у меня нет идей. Спасибо всем, кто может помочь. Пожалуйста, дайте мне знать, нужна ли какая-либо другая информация.

+4

Чтобы быть тупым, это действительно запутанный запрос, и это должно быть исправлено до того, как вы попытаетесь его оптимизировать; Я не могу с готовностью сказать о намеченной цели. Некоторые запутывающие вещи: а) вы делаете левые соединения, но затем помещаете ограничения в предложение where, эффективно делая их внутренними объединениями. б) Я не могу с легкостью объяснить, почему вы используете GROUP BY, поскольку не используется функция агрегата, и, следовательно, полученные данные неопределенны, одна из наиболее уродливых функций MySQL. Можете ли вы предоставить образцы данных и желаемый результат? – RedFilter

+1

Как указано в @RedFilter, предложение WHERE эффективно устраняет необходимость в LEFT JOINs в основном запросе. Кроме того, предложение WHERE предполагает, что пользователь должен иметь Tag = 8 и не должен иметь тег = 3. Это можно было бы получить более эффективным способом, который ЛЕВАЕТ СОЕДИНЯЕТ. – user2989408

+1

Я бы обратил внимание на комментарий RedFilters ... но с точки зрения оптимизированной точки зрения, вы, судя по всему, являетесь кандидатами выбора в своем предложении where. MySQL preforms подзапросит в том, где предложения ужасно плохо, и обычно лучше всего записывать как объединение, а не в предложение where. – Twelfth

ответ

1

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

SELECT User. id, User. username, User. password, User. role, User. created, User. modified, User. email, User. other_user_id, User. first_name, User. last_name, User. place_id, Resume. id, Resume. user_id, Resume. other_resume_id, Resume. other_user_id, Resume. file_extension, Resume. created, Resume. modified, Resume. is_deleted, Resume. has_file, Resume. is_stamped, Resume. is_active

ОТ streetofwalls. users AS User
LEFT JOIN my_database. attempts А.С. Attempt ВКЛ (Attempt. user_id = User. id И Attempt. test_id! = 5) LEFT JOIN my_database. reports А.С. Resume ВКЛ (Resume. user_id = User. id)

, my_database. users AS Пользователь1

LEFT JOIN my_database. tags_users А.С. TagUser на (User1. id = TagUser. user_id)

LEFT JOIN my_database. tags AS Tag ON (TagUser. tag_id = Tag. id)

ГДЕ User. id = User1.id И Attempt. test_id = 8 И Attempt. score> 60
И Resume. has_file = 1 И Tag. id = '8' И Tag. id! = '3' ГРУППА ПО User. id ЗАКАЗАТЬ НА Attempt. score DESC;

Смежные вопросы