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、それほどではありませんが、それでも)。ただし、各テーブルに 50,000 レコードを入力すると、違いがより顕著になります。

私の観点からすると、2番目のクエリはより多くのサブクエリを実行するため、動作が遅くなるはずです。

誰か説明してくれませんか?

4

1 に答える 1

4

違いは、要素がインデックスなしで決定される最初のクエリと比較して、2 番目の内部クエリ(SELECT sum(`amount`) FROM payments AS p WHERE u.id = p.`user`)で mysql がインデックスを使用していることです。Explainを使用すると、実行計画、関連する行数、およびサブクエリがインデックスを使用しているかどうかを確認できます。

シナリオの実行計画については、sqlFiddle (余分な列に注意してください)を参照してください。

于 2012-11-02T09:17:45.190 に答える