[英]Is it possible to make this query faster?
称呼,
我对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)
这是重构为使用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条记录。 对于笔记本电脑来说还不错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.