10個案例告訴你mysql不使用子查詢的原因

大家好舟误,我是 V 哥葡秒,上周跟一個哥們吃飯,技術(shù)人在一起嵌溢,你知道的眯牧,沒聊上一會兒,就轉(zhuǎn)到技術(shù)問題探討上了赖草,其中聊到數(shù)據(jù)庫子查詢的問題印象深刻学少,回來整理了以下10個案例說明不使用子查詢的問題,分享給大家秧骑。

首先版确,來說一下在MySQL中扣囊,不推薦使用子查詢和JOIN的原因,主要有以下幾點:

  1. 性能問題:子查詢在執(zhí)行時绒疗,MySQL需要創(chuàng)建臨時表來存儲內(nèi)層查詢的結(jié)果侵歇,查詢完畢后再刪除這些臨時表,這會增加CPU和IO資源的消耗吓蘑,產(chǎn)生慢查詢惕虑。JOIN操作本身效率也是硬傷,特別是當數(shù)據(jù)量很大時士修,性能難以保證枷遂。

  2. 索引失效:子查詢可能導(dǎo)致索引失效,因為MySQL會將查詢強行轉(zhuǎn)換為聯(lián)接來執(zhí)行棋嘲,這使得子查詢不能首先被執(zhí)行酒唉,如果外表很大,性能上會出問題沸移。

  3. 查詢優(yōu)化器的復(fù)雜度:子查詢會影響查詢優(yōu)化器的判斷痪伦,導(dǎo)致不夠優(yōu)化的執(zhí)行計劃。相比之下雹锣,聯(lián)表查詢更容易被優(yōu)化器理解和處理网沾。

  4. 數(shù)據(jù)傳輸開銷:子查詢可能導(dǎo)致大量不必要的數(shù)據(jù)傳輸,因為每個子查詢都需要將結(jié)果返回給主查詢蕊爵,而聯(lián)表查詢則可以通過一次查詢返回所需的所有數(shù)據(jù)辉哥,減少數(shù)據(jù)傳輸?shù)拈_銷。

  5. 維護成本:使用JOIN寫的SQL語句在修改表的schema時比較復(fù)雜攒射,成本較大醋旦,尤其是在系統(tǒng)較大時,不易維護会放。

針對這些原因饲齐,可以采取以下解決方案:

  1. 應(yīng)用層關(guān)聯(lián):在業(yè)務(wù)層單表查詢出數(shù)據(jù)后,作為條件給下一個單表查詢咧最,減少數(shù)據(jù)庫層的負擔捂人。

  2. 使用IN代替子查詢:如果子查詢結(jié)果集比較小,可以考慮使用“IN”操作符進行查詢矢沿,這在數(shù)據(jù)量較小的情況下滥搭,查詢效率更高。

  3. 使用WHERE EXISTS:WHERE EXISTS是一種比“IN”更好的方案咨察,它會檢查子查詢是否返回結(jié)果集论熙,查詢速度能夠明顯提高。

  4. 改寫為JOIN:使用JOIN查詢來替代子查詢摄狱,不需要建立臨時表脓诡,速度更快无午,如果查詢中使用索引,性能會更好祝谚。

接下來宪迟,V 哥通過10個案例來直觀的介紹一下。

案例1:查詢所有有庫存的商品信息交惯。

  • 原始查詢(使用子查詢):查詢字段太多次泽,就用*號替代了哈,不用在意席爽,實際項目中肯定是不這樣使用的意荤。
  SELECT * FROM products WHERE id IN (SELECT product_id FROM inventory WHERE stock > 0);

這個查詢會導(dǎo)致查詢速度慢,影響用戶體驗只锻。

  • 優(yōu)化方案(使用EXISTS):
  SELECT * FROM products WHERE EXISTS (SELECT 1 FROM inventory WHERE inventory.product_id = products.id AND inventory.stock > 0);

這個優(yōu)化方案可以大幅提升查詢速度玖像,改善用戶體驗。

案例2:使用EXISTS優(yōu)化子查詢

原始查詢

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA');

優(yōu)化方案

SELECT * FROM orders WHERE EXISTS (SELECT 1 FROM customers WHERE orders.customer_id = customers.customer_id AND customers.country = 'USA');

使用EXISTS代替IN子查詢可以減少回表查詢的次數(shù)齐饮,提高查詢效率捐寥。

案例3:使用JOIN代替子查詢

原始查詢

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA');

優(yōu)化方案

SELECT o.* FROM orders o JOIN customers c ON o.customer_id = c.customer_id WHERE c.country = 'USA';

使用JOIN代替子查詢可以減少子查詢的開銷,并且更容易利用索引祖驱。

案例4:優(yōu)化子查詢以減少數(shù)據(jù)量

原始查詢

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers);

優(yōu)化方案

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE active = 1);

限制子查詢返回的數(shù)據(jù)量握恳,減少主查詢需要檢查的行數(shù),提高查詢效率捺僻。

案例5:使用索引覆蓋

原始查詢

SELECT customer_id FROM customers WHERE country = 'USA';

優(yōu)化方案

CREATE INDEX idx_country ON customers(country);
SELECT customer_id FROM customers WHERE country = 'USA';

country字段創(chuàng)建索引乡洼,使得子查詢可以直接在索引中找到數(shù)據(jù),避免回表查詢匕坯。

案例6:使用臨時表優(yōu)化復(fù)雜查詢

原始查詢

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE last_order_date > '2023-01-01');

優(yōu)化方案

CREATE TEMPORARY TABLE temp_customers AS SELECT customer_id FROM customers WHERE last_order_date > '2023-01-01';
SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM temp_customers);

對于復(fù)雜的子查詢就珠,使用臨時表存儲中間結(jié)果,簡化查詢并提高性能醒颖。

案例7:使用窗口函數(shù)替代子查詢

原始查詢

SELECT employee_id, salary, (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id) AS avg_salary FROM employees e;

優(yōu)化方案

SELECT employee_id, salary, AVG(salary) OVER (PARTITION BY department_id) AS avg_salary FROM employees;

使用窗口函數(shù)替代子查詢,提高查詢效率壳炎。

案例8:優(yōu)化子查詢以避免全表掃描

原始查詢

SELECT * FROM users WHERE username IN (SELECT username FROM orders WHERE order_date = '2024-01-01');

優(yōu)化方案

CREATE INDEX idx_order_date ON orders(order_date);
SELECT * FROM users WHERE username IN (SELECT username FROM orders WHERE order_date = '2024-01-01');

order_date字段創(chuàng)建索引泞歉,避免全表掃描,提高子查詢效率匿辩。

案例9:使用LIMIT子句限制子查詢返回數(shù)據(jù)量

原始查詢

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA');

優(yōu)化方案

SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA' LIMIT 100);

使用LIMIT子句限制子查詢返回的數(shù)據(jù)量腰耙,減少主查詢需要處理的數(shù)據(jù)量,提高查詢效率铲球。

案例10:使用JOIN代替子查詢以利用索引

原始查詢

SELECT * FROM transactions WHERE product_id IN (SELECT product_id FROM products WHERE category = 'Equity');

優(yōu)化方案

SELECT t.* FROM transactions t JOIN products p ON t.product_id = p.product_id WHERE p.category = 'Equity';

使用JOIN代替子查詢挺庞,并且可以更容易地利用products表上的category索引。

這些案例展示了如何通過不同的優(yōu)化策略來提升MySQL查詢性能稼病,特別是在處理子查詢時选侨。

最后

通過上述分析和案例掖鱼,我們可以看到,在實際業(yè)務(wù)場景中援制,替代子查詢和JOIN的高效編程方法能夠在不同場景下顯著提升MySQL數(shù)據(jù)庫的查詢性能戏挡。在實際應(yīng)用中,應(yīng)根據(jù)具體業(yè)務(wù)需求和數(shù)據(jù)特點晨仑,靈活選擇合適的優(yōu)化方案褐墅。關(guān)注威哥愛編程,癡迷技術(shù)咱是認真滴洪己。官人妥凳,都看到這了,高低點個贊再走唄答捕,V 哥感謝你的支持逝钥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市噪珊,隨后出現(xiàn)的幾起案子晌缘,更是在濱河造成了極大的恐慌,老刑警劉巖痢站,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件磷箕,死亡現(xiàn)場離奇詭異,居然都是意外死亡阵难,警方通過查閱死者的電腦和手機岳枷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呜叫,“玉大人空繁,你說我怎么就攤上這事≈烨欤” “怎么了盛泡?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長娱颊。 經(jīng)常有香客問我傲诵,道長,這世上最難降的妖魔是什么箱硕? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任拴竹,我火速辦了婚禮,結(jié)果婚禮上剧罩,老公的妹妹穿的比我還像新娘栓拜。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布幕与。 她就那樣靜靜地躺著挑势,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纽门。 梳的紋絲不亂的頭發(fā)上薛耻,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音赏陵,去河邊找鬼饼齿。 笑死,一個胖子當著我的面吹牛蝙搔,可吹牛的內(nèi)容都是我干的缕溉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吃型,長吁一口氣:“原來是場噩夢啊……” “哼证鸥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起勤晚,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤枉层,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后赐写,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸟蜡,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年挺邀,在試婚紗的時候發(fā)現(xiàn)自己被綠了揉忘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡端铛,死狀恐怖泣矛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情禾蚕,我是刑警寧澤您朽,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站换淆,受9級特大地震影響虚倒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜产舞,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菠剩。 院中可真熱鬧易猫,春花似錦、人聲如沸具壮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至攘已,卻和暖如春炮赦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背样勃。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工吠勘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人峡眶。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓剧防,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辫樱。 傳聞我的和親對象是個殘疾皇子峭拘,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容