0

谁能帮我优化这个查询?需要 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;

这是解释结果

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
4

2 回答 2

0

您需要enrollment包含(至少部分)number、、term和的表上的索引status。您还需要一个employeeID索引employees(如果它还不是主键,它应该是)。

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

这将确保 mysqlenrollment首先使用索引在表中查找,然后再加入users表。

于 2012-09-12T19:56:17.573 回答
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;

你有一个JOIN从句 between enrollment.employeeIDand 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')在查询中使用语法来简化它。

于 2012-09-12T19:48:27.443 回答