通过删除子查询来提高查询速度

时间:2013-06-07 15:42:12

标签: sql performance sqlperformance

我希望加快这个问题。目前只需要超过20秒就可以执行,这很糟糕。

我找不到使用和JOIN函数删除子查询的方法。

SQL:

(

    SELECT
        `manual`.`id`,
        `fname`,
        `lname`,
        `email`,
        '' AS `company`,
        '' AS `level`,
        `completed_tests`.`assessment`,
        '' AS `st_ref`,
        '1' AS `manual`,
        `completed_tests`.`percentage`,
        '' AS `last_visit`,
        '' AS `joined`

    FROM
        `manual`

    LEFT JOIN `used_codes` ON `manual`.`id` = `used_codes`.`user` AND `used_codes`.`id` = (SELECT MAX(`id`) FROM `used_codes` WHERE `user` = `manual`.`id` AND `manual` = 1)
    LEFT JOIN `vcode` ON `manual`.`vcode` = `vcode`.`id`
    LEFT JOIN `groups` ON `vcode`.`group` = `groups`.`id`
    LEFT JOIN `completed_tests` ON `manual`.`id` = `completed_tests`.`user` AND `completed_tests`.`id` = (SELECT MAX(`id`) FROM `completed_tests` WHERE `user` = `manual`.`id` AND `manual` = 1)

)
UNION ALL
(

    SELECT
        `users`.`id`,
        `fname`,
        `lname`,
        `email`,
        `company`,
        `users`.`level`,
        `completed_tests`.`assessment`,
        `orders`.`st_ref`,
        '0' AS `manual`,
        `completed_tests`.`percentage`,
        `last_visit`,
        `joined`

    FROM
        `users`

    LEFT JOIN `orders` ON `users`.`id` = `orders`.`user` AND `orders`.`id` = (SELECT MAX(`id`) FROM `orders` WHERE `status` = 3 AND `user` = `users`.`id`)
    LEFT JOIN `used_codes` ON `users`.`id` = `used_codes`.`user` AND `used_codes`.`id` = (SELECT MAX(`id`) FROM `used_codes` WHERE `user` = `users`.`id` AND `manual` = 1)
    LEFT JOIN `vcode` ON `used_codes`.`vcode` = `vcode`.`id`
    LEFT JOIN `groups` ON `vcode`.`group` = `groups`.`id`
    LEFT JOIN `completed_tests` ON `users`.`id` = `completed_tests`.`user` AND `completed_tests`.`id` = (SELECT MAX(`id`) FROM `completed_tests` WHERE `user` = `users`.`id` AND `manual` = 0)

)

ORDER BY `lname` ASC, `fname` ASC;

为了让您了解数据库结构,有两个主要表,一个用于users,另一个用于manual。其他表包含其他数据,并与用户的ID和另一个名为manual的字段链接,以查看它们属于哪个数据库。

我遇到的问题是我需要该用户的数据来显示他们是否在其他表中有任何其他数据。当我使用JOIN函数测试时,记录将完全从结果中删除。

我认为需要重写的查询的主要部分是LEFT JOIN。我无法找到与此相同的方法:LEFT JOIN orders ON users.id = orders.user AND orders.id = (SELECT MAX(id) FROM orders WHERE status = 3 AND user = users.id)

1 个答案:

答案 0 :(得分:1)

如果您取出以下子查询,该怎么办?

SELECT MAX(id) FROM orders WHERE status = 3 AND user = users.id

将它们放入临时表并索引id。你绝对可以索引临时表,我发现当我试图优化子查询时,它会在性能上产生巨大的差异。

当然你必须删除user = user.id部分,但你可以保持status = 3部分。

您为一个大型查询支付一次价格(存储具有该状态的所有用户并为临时表编制索引),但随后所有后续调用都非常快。