簡體   English   中英

是否可以使此查詢更快?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM