2012-11-02 2 views
3

나는 다음 DB 구조재귀 쿼리가 조인 및 그룹화보다 빠릅니다.

-- ----------------------------------------------------- 
    -- 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; 

그리고 질문을 MySQL 서버 5.5을 사용하고있는하고있다 :이 쿼리

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, 많이는 아니지만 여전히). 그러나 각 테이블에 50,000 개의 레코드를 채우면 차이가 더 두드러집니다.

내 관점에서 두 번째 쿼리는 더 많은 하위 쿼리를 실행하므로 느리게 작동해야합니다.

누군가 나를 위해 설명해 주실 수 있습니까?

+1

는 한 번 봐 [확장 설명] (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 (추가 열에 유의하십시오) 시나리오의 실행 계획을 참조하십시오.

관련 문제