[英]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.