需要帮助优化连接

时间:2012-09-12 19:36:24

标签: mysql optimization join

任何人都可以帮我优化此查询吗?这需要15秒。如果我将WHERE子句移动到连接本身,仍然会得到相同的结果。

SELECT
`users`.`employeeID` as `username`,
`users`.`firstName` as `fname`,
`users`.`lastName` as `lname`
FROM `enrollment`
INNER JOIN `users` ON `enrollment`.`employeeID` = `users`.`employeeID`
WHERE `enrollment`.`number` = [int]
AND
`enrollment`.`term` = [int]
AND
(
`enrollment`.`status` = 'E'
OR
`enrollment`.`status` = 'M'
)
ORDER BY    
`users`.`lastName` ASC,
`users`.`firstName` ASC;

只要这个:

SELECT
`users`.`employeeID` as `username`,
`users`.`firstName` as `fname`,
`users`.`lastName` as `lname`
FROM `enrollment`
INNER JOIN
`users` ON `enrollment`.`employeeID` = `users`.`employeeID`
AND
`enrollment`.`number` = [int]
AND
`enrollment`.`term` = [int]
AND
(
`enrollment`.`status` = 'E'
OR
`enrollment`.`status` = 'M'
)
ORDER BY    
`users`.`lastName` ASC,
`users`.`firstName` ASC;

这是EXPLAIN结果

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  users   ALL PRIMARY NULL    NULL    NULL    52925   Using filesort
1   SIMPLE  enrollment  ref employeeID,number_term  employeeID  9   ezlrn.users.employeeID  2   Using where

2 个答案:

答案 0 :(得分:0)

要详尽地回答,我们需要查看您获得的EXPLAIN SELECT...(your query)查询计划,以及已经存在的索引结构。

假设你还没有索引(除了PRIMARY KEY之外),那就是问题,让我们看看如何掀起一些东西(可能进一步改进):

SELECT
    `users`.`employeeID` as `username`,
    `users`.`firstName` as `fname`,
    `users`.`lastName` as `lname`
FROM `enrollment`
    INNER JOIN `users` ON `enrollment`.`employeeID` = `users`.`employeeID`
WHERE `enrollment`.`number` = [int]
    AND
    `enrollment`.`term` = [int]
    AND
    (
        `enrollment`.`status` = 'E'
    OR
    `enrollment`.`status` = 'M'
    )
    ORDER BY    
        `users`.`lastName` ASC,
        `users`.`firstName` ASC;

JOINenrollment.employeeID之间有一个users.employeeID子句。

所以你需要的前几个索引就在那里:

-- CREATE INDEX enrollment_ndx ON enrollment(employeeID); -- wait on this one
CREATE INDEX users_ndx ON users(employeeID);

然后WHERE子句包含一些可以有用索引的条件。所以enrollment的最终索引是:

CREATE INDEX enrollment_ndx ON enrollment(employeeID, number, term, status);

尝试在注册和用户上创建索引,然后重试(发布查询计划)。

注意:您还可以在查询中使用语法enrollment.status IN ('M', 'E')来简化它。

答案 1 :(得分:0)

您需要enrollment表上包含({至少部分)numbertermstatus的索引。您还需要employeeID上的employees索引(如果它不是主键,它应该是主键)。

CREATE INDEX idx1 ON enrollment (number, term, status);
CREATE INDEX idx2 ON users (employeeID); // if needed

这将确保mysql首先使用索引在enrollment表中查找并再次加入users表。