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记录填充每个表格,差异会更加明显。
从我的角度来看,第二个查询执行更多的子查询,所以它应该工作得更慢。
有人可以给我解释吗?
考虑看看[Explain Extended](http://dev.mysql.com/doc/refman/5.0/en/explain-extended.html) – Andomar
您的示例中没有*递归*查询 –
为什么'GROUP BY Name'而不是'GROUP BY u.id'? 'User.Name'这个列不是'UNIQUE',所以这可能会给出错误的结果(这可能是两个查询的时间差异的原因) –