鍍金池/ 問(wèn)答/Python  數(shù)據(jù)庫(kù)/ 如何提高這個(gè) sql 語(yǔ)句的查詢效率

如何提高這個(gè) sql 語(yǔ)句的查詢效率

圖片描述

數(shù)據(jù)是 MySQL 的實(shí)例數(shù)據(jù)庫(kù),這是數(shù)據(jù)庫(kù)的地址,有心幫忙的朋友可以直接在數(shù)據(jù)庫(kù)上進(jìn)行測(cè)試。

host:125.42.176.217:63306
user:ousikongjian
password: hawk@#
database: employees

需求

查詢 1999 年時(shí)期,部門、主管及部門員工的詳細(xì)信息,需 Department, DeptManager, Employees, Title, DeptEmp 五個(gè)表聯(lián)合查詢,其中對(duì) Employees, Title 兩個(gè)表進(jìn)行了兩次查詢,多次查詢的時(shí)候注意設(shè)置別名。

結(jié)果是: 返回字段為     dp.dept_no(部門編號(hào)), dept_name(部門名稱), dm_emp_no(主管編號(hào)),
dm_title(主管頭銜), dm_birth_date(主管生日),dm_first_name(主管第一名稱),
dm_last_name(主管姓氏), dm_gender(主管性別), dm_hire_date(主管聘任日期), 
dm_from_date(主管任期開始時(shí)間), dm_to_date(主管任期結(jié)束時(shí)間),emp_no(員工編號(hào)),title(員工頭銜),
t_from_date(頭銜授予時(shí)間), t_to_date(頭銜結(jié)束時(shí)間),birth_date(員工生日), 
first_name(員工第一名稱), last_name(員工姓氏), gender(員工性別), hire_date(員工聘任日期), 
from_date(員工在本部門任期開始時(shí)間), to_date(員工在本部門任期結(jié)束時(shí)間)

自己寫的 SQL 語(yǔ)句如下

SELECT
    d.dept_no,
    d.dept_name,
    em.emp_no AS dm_emp_no,
    t1.title AS dm_title,
    em.birth_date AS dm_birth_date,
    em.first_name AS dm_first_name,
    em.last_name AS dm_last_name,
    em.gender AS dm_gender,
    em.hire_date AS dm_hire_date,
    dm.from_date AS dm_from_date,
    dm.to_date AS dm_to_date,
    e.emp_no,
    t2.title,
    t2.from_date AS t_from_date,
    t2.to_date AS t_to_date,
    e.birth_date,
    e.first_name,
    e.last_name,
    e.gender,
    e.hire_date,
    de.from_date,
    de.to_date
FROM
    employees e
JOIN dept_emp de ON de.emp_no = e.emp_no
JOIN departments d ON d.dept_no = de.dept_no
JOIN dept_manager dm ON dm.dept_no = d.dept_no
JOIN employees em ON dm.emp_no = em.emp_no
JOIN titles t1 ON t1.emp_no = em.emp_no
AND t1.from_date = dm.from_date # 這里取了巧,認(rèn)為部門負(fù)責(zé)人在負(fù)責(zé)該部門的頭銜時(shí)間和任期是一致的。
AND t1.to_date = dm.to_date
JOIN titles t2 ON t2.emp_no = e.emp_no
WHERE
    (
        '1999' BETWEEN YEAR (de.from_date)
        AND YEAR (de.to_date)
    )
AND (
    '1999' BETWEEN YEAR (dm.from_date)
    AND YEAR (dm.to_date)
)
AND (
    '1999' BETWEEN YEAR (t2.from_date)
    AND YEAR (t2.to_date)
)
GROUP BY
    e.emp_no,
    d.dept_no,
    d.dept_name,
    em.emp_no,
    t1.title,
    em.birth_date,
    em.first_name,
    em.last_name,
    em.gender,
    em.hire_date,
    dm.from_date,
    dm.to_date,
    t2.title,
    t2.from_date,
    t2.to_date,
    e.birth_date,
    e.first_name,
    e.last_name,
    e.gender,
    e.hire_date,
    de.from_date,
    de.to_date

查詢的結(jié)果是 281354 條數(shù)據(jù),查詢時(shí)間為 33.709 秒。

問(wèn)題

希望大家?guī)兔?,通過(guò)優(yōu)化 SQL 語(yǔ)句提高查詢效率。

sql to sqlalchemy 項(xiàng)目送上真摯的問(wèn)候,希望您能夠喜歡!?。?/a>

回答
編輯回答
浪蕩不羈

不建議關(guān)聯(lián)這么多張表,只查詢最基本的信息,其他如部門,主管,頭銜,做出key=>value的樣子,通過(guò)編程語(yǔ)言的foreach添加進(jìn)去。

另外groupby的時(shí)候,【select from (select from t1 group by ) left join t2. 】先分組縮小join的數(shù)據(jù)。
多寫幾種sql,比較下執(zhí)行時(shí)間,從中選擇最高效的一種。

2018年4月3日 02:11
編輯回答
尋仙

字段有點(diǎn)多,后面有時(shí)候慢慢看看。
不過(guò),你 SQL 中那么多 group by ,確定沒問(wèn)題。
還有就是,員工的部門,薪酬,都存在歷史時(shí)期的數(shù)據(jù),不同時(shí)期的這類數(shù)據(jù)在使用時(shí),要么看確定的某一個(gè)員工的多時(shí)期情況,要看確定時(shí)期的多員工情況,但是,并沒有看到有類似的過(guò)濾條件。換句話說(shuō),多時(shí)期,多員工的數(shù)據(jù)出來(lái),基本不會(huì)直接做什么用的,還要再處理。

2017年10月19日 20:08
編輯回答
傻丟丟

把group by全去了,我這邊100條0.195s, 帶著group by 100條8.12s(group by會(huì)引發(fā)Using filesort)

2017年12月8日 10:41
編輯回答
我甘愿

除了樓上朋友提的group by的建議外,我建議把where那一塊也給優(yōu)化下。
因?yàn)槟悴槌鰜?lái)的數(shù)據(jù)較多,有28W條以上,所以應(yīng)該還是有必要把索引也用上的。
優(yōu)化方式:
1.為where中的相關(guān)字段添加索引,如字段dm.from_date
2.不要對(duì)這些字段使用YEAR等方法,這樣會(huì)導(dǎo)致索引失效。
例如'1999' BETWEEN YEAR (de.from_date) AND YEAR (de.to_date)修改為
de.from_date < '1999' and de.to_date > '1999'
(因?yàn)闆]太明白你要查的數(shù)據(jù)的需求,所以可能寫的和你想要的不太一樣,但是大致意思就這個(gè)樣子。)

2017年1月31日 22:23