问题
I have the following query that takes a really long time to execute. I need to speed it up, but I'm at a lost as to what technique to use. This is the query:
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;
This query generates the following explain:
As you can see, I have several indexes on this query. At the moment only the resume table is not able to be indexed. Is is possible to index this table in the context of this query? Is there some other way to speed this query up that I have not thought of? Its prohibitively slow for its intended function and I'm out of ideas. Thank you to anyone who can help. Please let me know if any other information is needed.
回答1:
try inner join instead of sub-query it is default to guide query without running on data,but may be following the query will help you.
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
)
, 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
User
.id
= User1
.id
AND Attempt
.test_id
= 8
AND Attempt
.score
> 60
AND Resume
.has_file
= 1
AND Tag
.id
= '8' AND Tag
.id
!= '3'
GROUP BY User
.id
ORDER BY Attempt
.score
DESC;
来源:https://stackoverflow.com/questions/20248803/mysql-optimization-based-on-explain