2012-11-02 40 views
3

我使用MySQL服务器5.5,并有下一个数据库结构为什么递归查询比加入和分组更快?

-- ----------------------------------------------------- 
    -- Table `mydb`.`User` 
    -- ----------------------------------------------------- 
    CREATE TABLE IF NOT EXISTS `mydb`.`User` (
     `id` INT NOT NULL , 
     `Name` VARCHAR(45) NOT NULL , 
     PRIMARY KEY (`id`)) 
    ENGINE = InnoDB; 


    -- ----------------------------------------------------- 
    -- Table `mydb`.`Payments` 
    -- ----------------------------------------------------- 
    CREATE TABLE IF NOT EXISTS `mydb`.`Payments` (
     `id` INT NOT NULL , 
     `Amount` DOUBLE NOT NULL , 
     `User` INT NOT NULL , 
     PRIMARY KEY (`id`) , 
     INDEX `fk_Payments_User` (`User` ASC) , 
     CONSTRAINT `fk_Payments_User` 
     FOREIGN KEY (`User`) 
     REFERENCES `mydb`.`User` (`id`) 
     ON DELETE NO ACTION 
     ON UPDATE NO ACTION) 
    ENGINE = InnoDB; 


    -- ----------------------------------------------------- 
    -- Table `mydb`.`Extras` 
    -- ----------------------------------------------------- 
    CREATE TABLE IF NOT EXISTS `mydb`.`Extras` (
     `id` INT NOT NULL , 
     `ExtraAmount` DOUBLE NOT NULL , 
     PRIMARY KEY (`id`) , 
     INDEX `fk_Extras_Payments1` (`id` ASC) , 
     CONSTRAINT `fk_Extras_Payments1` 
     FOREIGN KEY (`id`) 
     REFERENCES `mydb`.`Payments` (`id`) 
     ON DELETE NO ACTION 
     ON UPDATE NO ACTION) 
    ENGINE = InnoDB; 

而问题是:为什么这个查询

SELECT u.*, sum(`amount`),sum(`ExtraAmount`) 
    FROM `user` AS `u` 
    LEFT JOIN payments AS p ON u.id = p.`user` 
    INNER JOIN extras AS e ON p.id = e.id 
    WHERE `Name` = 'abc' 
    GROUP BY `Name` 

工作比这

SELECT *, IFNULL((SELECT sum(`amount`) 
         FROM payments AS p 
         WHERE u.id = p.`user`),0) AS `TotalAmount`, 
       IFNULL((SELECT sum(`ExtraAmount`) 
         FROM payments AS p 
         INNER JOIN extras AS e ON p.id = e.id 
         WHERE p.`User` = u.id),0) AS `sum2` 
    FROM `user` AS `u` 
    WHERE `Name` = 'abc' 

慢有差异甚至在空DB(0.0001-0002s,不多,但仍然)。但是如果你用50k记录填充每个表格,差异会更加明显。

从我的角度来看,第二个查询执行更多的子查询,所以它应该工作得更慢。

有人可以给我解释吗?

+1

考虑看看[Explain Extended](http://dev.mysql.com/doc/refman/5.0/en/explain-extended.html) – Andomar

+1

您的示例中没有*递归*查询 –

+0

为什么'GROUP BY Name'而不是'GROUP BY u.id'? 'User.Name'这个列不是'UNIQUE',所以这可能会给出错误的结果(这可能是两个查询的时间差异的原因) –

回答

4

不同之处在于,在您的第二个内部查询(SELECT sum(`amount`) FROM payments AS p WHERE u.id = p.`user`)中mysql正在使用索引,与第一个查询相比,其中元素是在没有索引的情况下确定的。使用explain,您将能够看到执行计划,涉及的行数以及子查询是否使用索引。

请参阅sqlFiddle(请注意额外的列)为您的方案的执行计划。

相关问题