简体   繁体   中英

Why recursive query faster than join and group by?

I am using MySQL server 5.5 and have next db structure

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

And question is: Why this query

    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`

works slower than this one

    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'

There is difference even on empty DB(0.0001-0002s, not much, but still). But if you populate each table with 50k records, difference will be more noticeable.

From my point of view second query executes way more sub queries, so it should work slower.

Can somebody explain it for me please?

The difference is that on your second inner query (SELECT sum(`amount`) FROM payments AS p WHERE u.id = p.`user`) mysql is using an index, compared to the first query, where the elements are determined without the index. Using explain you will be able to see the execution plan, how many rows are involved and if the subqueries are using or not indexes.

See sqlFiddle (note the extra columns) for the execution plan of your scenario.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM