對MySQL子查詢的簡單改寫優(yōu)化
使用過oracle或者其他關(guān)系數(shù)據(jù)庫的DBA或者開發(fā)人員都有這樣的經(jīng)驗,在子查詢上都認(rèn)為數(shù)據(jù)庫已經(jīng)做過優(yōu)化,能夠很好的選擇驅(qū)動表執(zhí)行,然后在把該經(jīng)驗移植到mysql數(shù)據(jù)庫上,但是不幸的是,mysql在子查詢的處理上有可能會讓你大失所望,在我們的生產(chǎn)系統(tǒng)上就由于碰到了這個問題:
select i_id, sum(i_sell) as i_sell from table_data where i_id in (select i_id from table_data where Gmt_create >= '2011-10-07 00:00:00′) group by i_id;
(備注:sql的業(yè)務(wù)邏輯可以打個比方:先查詢出10-07號新賣出的100本書,然后在查詢這新賣出的100本書在全年的銷量情況)。
這條sql之所以出現(xiàn)的性能問題在于mysql優(yōu)化器在處理子查詢的弱點,mysql優(yōu)化器在處理子查詢的時候,會將將子查詢改寫。通常情況下,我們希望由內(nèi)到外,先完成子查詢的結(jié)果,然后在用子查詢來驅(qū)動外查詢的表,完成查詢;但是mysql處理為將會先掃描外面表中的所有數(shù)據(jù),每條數(shù)據(jù)將會傳到子查詢中與子查詢關(guān)聯(lián),如果外表很大的話,那么性能上將會出現(xiàn)問題;
針對上面的查詢,由于table_data這張表的數(shù)據(jù)有70W的數(shù)據(jù),同時子查詢中的數(shù)據(jù)較多,有大量是重復(fù)的,這樣就需要關(guān)聯(lián)近70W次,大量的關(guān)聯(lián)導(dǎo)致這條sql執(zhí)行了幾個小時也沒有執(zhí)行完成,所以我們需要改寫sql:
SELECT t2.i_id, SUM(t2.i_sell) AS sold FROM (SELECT distinct i_id FROM table_data WHERE gmt_create >= '2011-10-07 00:00:00′) t1, table_data t2 WHERE t1.i_id = t2.i_id GROUP BY t2.i_id;
我們將子查詢改為了關(guān)聯(lián),同時在子查詢中加上distinct,減少t1關(guān)聯(lián)t2的次數(shù);
改造后,sql的執(zhí)行時間降到100ms以內(nèi)。
相關(guān)文章
MySQL使用GROUP?BY使用技巧和注意事項總結(jié)
GROUP?BY?子句是?在MySQL?中用于將查詢結(jié)果按照指定的列或表達(dá)式進(jìn)行分組的關(guān)鍵字,它通常與聚合函數(shù)一起使用,能夠?qū)γ總€分組進(jìn)行統(tǒng)計或計算,本文給大家總結(jié)了MySQL使用GROUP?BY使用技巧和注意事項,需要的朋友可以參考下2024-05-05
MySQL如何快速的創(chuàng)建千萬級測試數(shù)據(jù)
這篇文章主要給大家介紹了關(guān)于MySQL如何快速的創(chuàng)建千萬級測試數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
MySQL使用觸發(fā)器如何實現(xiàn)CHECK檢查約束的功能
這篇文章主要介紹了MySQL使用觸發(fā)器如何實現(xiàn)CHECK檢查約束的功能,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01

