我是MySQL的新手,特别是生成查询,我想知道是否有可能让我的查询执行得更快?我在这里使用员工数据库:https://github.com/datacharmer/test_db
现在我必须提出的查询需要回答以下问题:"•对于每个部门,列出每十年出生的员工人数及其平均工资"
这就是我提出的:
SELECT DISTINCT d.dept_name, count(e.emp_no), AVG(s.salary), ROUND(YEAR(e.birth_date), -1) AS birth_date
FROM employees e, departments d, salaries s, dept_emp de
WHERE de.emp_no = e.emp_no AND de.dept_no = d.dept_no
AND e.emp_no = s.emp_no
GROUP BY d.dept_name,
ROUND(YEAR(e.birth_date), -1);
它有效,它产生教授想要的结果,但它很慢,大约需要11秒才能执行。我的查询中是否存在执行缓慢的问题?
编辑:
描述的表:
mysql> explain dept_emp_latest_date;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | | NULL | |
| from_date | date | YES | | NULL | |
| to_date | date | YES | | NULL | |
+-----------+---------+------+-----+---------+-------+
3 rows in set (0.01 sec)
mysql> explain dept_manager
-> ;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| dept_no | char(4) | NO | PRI | NULL | |
| from_date | date | NO | | NULL | |
| to_date | date | NO | | NULL | |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> explain employees;
+------------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| birth_date | date | NO | | NULL | |
| first_name | varchar(14) | NO | | NULL | |
| last_name | varchar(16) | NO | | NULL | |
| gender | enum('M','F') | NO | | NULL | |
| hire_date | date | NO | | NULL | |
+------------+---------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
mysql> explain salaries;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| salary | int(11) | NO | | NULL | |
| from_date | date | NO | PRI | NULL | |
| to_date | date | NO | | NULL | |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> explain titles;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| title | varchar(50) | NO | PRI | NULL | |
| from_date | date | NO | PRI | NULL | |
| to_date | date | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+
4 rows in set (0.00 sec)
mysql> explain departments;
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| dept_no | char(4) | NO | PRI | NULL | |
| dept_name | varchar(40) | NO | UNI | NULL | |
+-----------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)
mysql> explain current_dept_emp;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | | NULL | |
| dept_no | char(4) | NO | | NULL | |
| from_date | date | YES | | NULL | |
| to_date | date | YES | | NULL | |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.02 sec)
mysql> explain dept_emp;
+-----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no | int(11) | NO | PRI | NULL | |
| dept_no | char(4) | NO | PRI | NULL | |
| from_date | date | NO | | NULL | |
| to_date | date | NO | | NULL | |
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)
答案 0 :(得分:1)
您的查询重构为使用21世纪的JOIN语法。
SELECT DISTINCT d.dept_name, count(e.emp_no), AVG(s.salary),
ROUND(YEAR(e.birth_date), -1) AS birth_date
FROM employees e
JOIN salaries s ON e.emp_no = s.emp_no
JOIN dept_emp de ON de.emp_no = e.emp_no
JOIN departments d ON de.dept_no = d.dept_no
GROUP BY d.dept_name, ROUND(YEAR(e.birth_date), -1);
请注意,DISTINCT
在聚合(GROUP BY)查询中是多余的。摆脱它需要几秒钟。
但请注意salaries
表包含历史薪资数据。每行包含from_date
和to_date
。 from_date
列是该表的主键的一部分以及员工编号。因此,您的查询会不加区分地平均一大堆薪资数据,并且会记录太多的记录。
此查询需要4.6秒左右(我的机器速度与您的相同,第一次查询需要11秒)。对于您提供的数据,它更有意义,因为它会提取特定时间点的工资记录和部门关联记录,而不是处理整个数据。
SELECT d.dept_name, COUNT(e.emp_no), AVG(s.salary),
ROUND(YEAR(e.birth_date), -1) AS birth_date
FROM employees e
JOIN salaries s ON e.emp_no = s.emp_no
JOIN dept_emp de ON de.emp_no = e.emp_no
JOIN departments d ON de.dept_no = d.dept_no
WHERE s.from_date<='2014-01-01' AND s.to_date >'2014-01-01'
AND de.from_date<='2014-01-01' AND de.to_date >'2014-01-01'
GROUP BY d.dept_name, ROUND(YEAR(e.birth_date), -1);
它正在处理25万个员工记录,因此它每毫秒处理52个记录。对笔记本电脑来说还不错。