MySQL,优化查询10秒执行

时间:2016-07-20 10:57:20

标签: mysql

SELECT 
 `User`.`id` AS id, 
 `User`.`f_name` AS name, 
 `User`.`l_name` AS surname, 
 `User`.`discharge` AS discharge, SUM(`Hour`.`normal`) + SUM(`Hour`.`full`) + SUM(`Hour`.`half`) workedHours,
 (SUM(Hour.day_off_id = 16))*8 AS hourFracht
FROM `kadry`.`users` AS `User`
LEFT JOIN `kadry`.`Hours` AS `Hour` ON (`Hour`.`subordinate_id` = `User`.`id` AND DATE(`Hour`.`date`) BETWEEN '2016-06-01' AND '2016-06-30')
WHERE (`User`.`discharge` IS NULL OR DATE(`User`.`discharge`) > '2016-06-30') AND `User`.`role` = 'regular' AND `User`.`active` = '1'
GROUP BY `User`.`id`
ORDER BY `User`.`assigned` ASC, `User`.`l_name` ASC

我有这个属性的表:

CREATE TABLE `hours` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `date` DATE NOT NULL,
    `hour_from` FLOAT NULL DEFAULT NULL,
    `hour_to` FLOAT NULL DEFAULT NULL,
    `subordinate_id` VARCHAR(11) NOT NULL,
    `supervisor_id` VARCHAR(11) NOT NULL,
    `max_synchro` TINYINT(1) NOT NULL DEFAULT '0',
    `day_off_id` SMALLINT(2) NULL DEFAULT NULL,
    `night` FLOAT NOT NULL DEFAULT '0',
    `half` FLOAT NOT NULL DEFAULT '0',
    `full` FLOAT NOT NULL DEFAULT '0',
    `normal` FLOAT NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`),
    UNIQUE INDEX `date` (`date`, `subordinate_id`),
    INDEX `subordinate_id` (`subordinate_id`),
    INDEX `supervisor_id` (`supervisor_id`),
    INDEX `date_2` (`date`),
    CONSTRAINT `users_id` FOREIGN KEY (`subordinate_id`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
    CONSTRAINT `userssupervisors` FOREIGN KEY (`supervisor_id`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=417864
;

表格时间有400k行以上查询需要10-13秒 我能做什么 ?添加更多索引或其他内容?

修改

CREATE TABLE `users` (
    `id` VARCHAR(11) NOT NULL COLLATE 'utf8_general_ci',
    `l_name` VARCHAR(80) NOT NULL COLLATE 'utf8_polish_ci',
    `f_name` VARCHAR(80) NOT NULL COLLATE 'utf8_polish_ci',
    `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `department` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',
    `username` VARCHAR(40) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
    `password` VARCHAR(40) NOT NULL DEFAULT '' COLLATE 'utf8_general_ci',
    `role` ENUM('admin','regular','superior','manager') NOT NULL DEFAULT 'regular' COLLATE 'utf8_general_ci',
    `assigned` VARCHAR(15) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
    `discharge` DATE NULL DEFAULT NULL,
    `active` TINYINT(1) NOT NULL DEFAULT '1',
    `last_entry` DATE NULL DEFAULT NULL,
    `in_use` VARCHAR(11) NOT NULL DEFAULT '0' COLLATE 'utf8_general_ci',
    `info` TEXT NULL COLLATE 'utf8_polish_ci',
    `id_user_card` INT(11) NULL DEFAULT NULL,
    `email` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
    `include_raport` TINYINT(1) NOT NULL DEFAULT '1',
    `in_collections` TINYINT(1) NOT NULL DEFAULT '1',
    `locker_number` INT(11) UNSIGNED NULL DEFAULT NULL,
    PRIMARY KEY (`id`),
    INDEX `assigned` (`assigned`),
    INDEX `role` (`role`),
    INDEX `active` (`active`),
    INDEX `id_index` (`id`),
    INDEX `discharge` (`discharge`),
    CONSTRAINT `department_id3` FOREIGN KEY (`assigned`) REFERENCES `departments` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_polish_ci'
ENGINE=InnoDB
;

1 个答案:

答案 0 :(得分:0)

首先,我会用表别名重写查询,以便更容易阅读:

SELECT u.id, u.f_name AS name, u.l_name AS surname, u.discharge,
       SUM(h.`normal`) + SUM(h.`full`) + SUM(h.`half`) as workedHours,
       SUM(h.day_off_id = 16) * 8 AS hourFracht
FROM `kadry`.`users` u LEFT JOIN
     `kadry`.`Hours` h
     ON (h.subordinate_id = u.id AND
        DATE(h.date) BETWEEN '2016-06-01' AND '2016-06-30')
WHERE (u.discharge IS NULL OR DATE(u.discharge) > '2016-06-30') AND
      u.`role` = 'regular' AND u.`active` = '1'
GROUP BY u.id
ORDER BY u.`assigned` ASC, `User`.`l_name` ASC;

索引可以提供帮助。我建议:users(role, active, discharge, id)hours(subordinate_id, date)