MySQL數(shù)據(jù)庫(kù)社招必考題:索引如何優(yōu)化WHERE子句?
大家好,我是小米,一個(gè)31歲、天天被面試題支配的社畜程序員。最近后臺(tái)有小伙伴跟我說(shuō):“小米,你能不能聊聊 WHERE子句優(yōu)化?上次面試官問(wèn)我,我一緊張就只說(shuō)了‘建索引’,結(jié)果當(dāng)場(chǎng)涼透了。”
哈哈,這個(gè)問(wèn)題我太有感觸了!因?yàn)槲耶?dāng)年第一次參加社招面試的時(shí)候,面試官問(wèn)的第一個(gè)SQL問(wèn)題就是:
“如果SQL語(yǔ)句的WHERE子句效率很低,你會(huì)怎么優(yōu)化?”
我當(dāng)時(shí)也是秒答:“建索引啊!”結(jié)果面試官笑了笑,說(shuō):“嗯,光會(huì)說(shuō)這個(gè),說(shuō)明你只停留在表面。”那一刻,我才意識(shí)到:優(yōu)化WHERE子句遠(yuǎn)遠(yuǎn)不只是建個(gè)索引那么簡(jiǎn)單。
今天這篇文章,就帶大家從面試題的角度,系統(tǒng)聊聊 如何優(yōu)化WHERE子句,不僅告訴你該怎么答題,還會(huì)順帶幫你理清思路,以后再遇到類(lèi)似問(wèn)題,你能胸有成竹地侃侃而談。
解題方法:面試官想聽(tīng)什么?
面試官拋出這個(gè)問(wèn)題,本質(zhì)上是考察你兩點(diǎn):
1、是否具備定位低效SQL的能力
你得知道,SQL變慢的根源在哪。是不是走了全表掃描?是不是索引沒(méi)用上?是不是數(shù)據(jù)量爆炸?
2、是否有系統(tǒng)化的優(yōu)化思路
面試官要聽(tīng)的不是你一上來(lái)就說(shuō)“加索引”,而是希望你能有邏輯:
- 先定位SQL語(yǔ)句是否低效;
- 再分析低效的原因;
- 最后給出逐步優(yōu)化的方案。
所以,正確的解題框架應(yīng)該是:
第一步:定位低效SQL
- 打開(kāi)慢查詢(xún)?nèi)罩荆╯low query log),確認(rèn)問(wèn)題SQL。
- 用 EXPLAIN 查看執(zhí)行計(jì)劃,看是否走了索引、是否出現(xiàn) ALL(全表掃描)。
第二步:分析原因
- 索引缺失?
- WHERE子句里用了不合適的寫(xiě)法?
- 數(shù)據(jù)訪(fǎng)問(wèn)量過(guò)大?
- 還是語(yǔ)句本身過(guò)于復(fù)雜?
第三步:逐項(xiàng)排查,提出優(yōu)化方法
- 索引問(wèn)題 → 建合適的索引。
- 語(yǔ)句寫(xiě)法問(wèn)題 → 調(diào)整寫(xiě)法,避免函數(shù)/表達(dá)式。
- 數(shù)據(jù)訪(fǎng)問(wèn)問(wèn)題 → 限制列數(shù)、分頁(yè)優(yōu)化。
- 特定情況 → 用全文索引、分庫(kù)分表、緩存。
這樣答題,面試官會(huì)覺(jué)得你有方法論,而不是只會(huì)背八股文。
接下來(lái)我們進(jìn)入實(shí)戰(zhàn)。WHERE子句為什么會(huì)慢?我整理了10個(gè)常見(jiàn)場(chǎng)景,面試時(shí)直接說(shuō)出來(lái),絕對(duì)加分。
缺少索引或索引沒(méi)用上
問(wèn)題:查詢(xún)條件的列沒(méi)有索引,或者索引被寫(xiě)法“廢掉了”。
優(yōu)化:在 WHERE、ORDER BY、GROUP BY 常用列上建合適的索引。
舉例:

在 age 上建索引,就能避免全表掃描。
WHERE子句對(duì)字段進(jìn)行 NULL 判斷
問(wèn)題:

這種寫(xiě)法,索引基本無(wú)效。
優(yōu)化:用默認(rèn)值替代 NULL,或者在設(shè)計(jì)表時(shí)避免 NULL。
使用 != 或 <>
問(wèn)題:

會(huì)導(dǎo)致引擎放棄索引,轉(zhuǎn)為全表掃描。
優(yōu)化:用范圍查詢(xún)代替,比如:

使用 OR 連接條件
問(wèn)題:

大概率會(huì)導(dǎo)致全表掃描。
優(yōu)化:用 UNION ALL 拆開(kāi)兩條SQL,再加索引。
濫用 IN 和 NOT IN
問(wèn)題:

范圍太大時(shí)會(huì)拖慢查詢(xún)。
優(yōu)化:
- 用 EXISTS 替代。
- 或者把大范圍數(shù)據(jù)拆成小批次。
模糊查詢(xún) %xxx%
問(wèn)題:

前置 %,索引直接失效。
優(yōu)化:
- 改成 name like '小米%';
- 用全文索引(FULLTEXT)。
WHERE子句里用參數(shù)
問(wèn)題:

參數(shù)在編譯時(shí)未知,優(yōu)化器沒(méi)法用索引。
優(yōu)化:用存儲(chǔ)過(guò)程或拼接SQL。
對(duì)字段做表達(dá)式操作
問(wèn)題:

amount 上的索引會(huì)失效。
優(yōu)化:改寫(xiě)成:

對(duì)字段做函數(shù)操作
問(wèn)題:

同樣廢掉索引。
優(yōu)化:改寫(xiě)成:

在 = 左邊使用函數(shù)或運(yùn)算
問(wèn)題:

索引無(wú)效。
優(yōu)化:改成:

WHERE子句優(yōu)化思路:一個(gè)小故事
給大家講個(gè)真實(shí)的小插曲。
之前我們項(xiàng)目里有個(gè)報(bào)表查詢(xún),SQL長(zhǎng)這樣:

一跑就卡,幾十萬(wàn)行數(shù)據(jù),跑了30秒。
后來(lái)我們排查發(fā)現(xiàn):
- year(join_date) 把索引廢掉了。
- order by salary desc 沒(méi)索引,導(dǎo)致額外排序。
于是我們做了兩步優(yōu)化:
- 改寫(xiě)SQL,把函數(shù)去掉:

- 給 salary 建索引。
結(jié)果呢?SQL從30秒縮短到不到1秒!老板看了直接夸:“小米,SQL優(yōu)化小能手!”
這件事給我一個(gè)啟發(fā):SQL優(yōu)化不是玄學(xué),而是細(xì)節(jié)的積累。
總結(jié):答題萬(wàn)能公式
面試時(shí)如果被問(wèn)到“如何優(yōu)化WHERE子句”,你完全可以用下面這個(gè)萬(wàn)能公式來(lái)回答:
- 先定位問(wèn)題:開(kāi)啟慢查詢(xún)?nèi)罩?,?EXPLAIN 看執(zhí)行計(jì)劃。
- 從索引入手:WHERE、ORDER BY、GROUP BY 列上建索引。
- 排查寫(xiě)法問(wèn)題:避免 !=、<>、OR、IN、NOT IN、前置 %、函數(shù)/表達(dá)式操作等。
- 優(yōu)化特定情況:用全文索引、分批查詢(xún)、改寫(xiě)SQL。
- 逐層遞進(jìn):從索引 → 數(shù)據(jù)訪(fǎng)問(wèn) → 語(yǔ)句寫(xiě)法 → 特殊優(yōu)化。
這樣一套邏輯說(shuō)下來(lái),面試官絕對(duì)會(huì)覺(jué)得:哇,這小伙子有經(jīng)驗(yàn)、有思路,不是只會(huì)背書(shū)。
最后的話(huà)
寫(xiě)到這里,我想說(shuō),SQL優(yōu)化其實(shí)是一種“武功修煉”。一開(kāi)始你可能只會(huì)用“索引”這把大刀亂砍,但隨著經(jīng)驗(yàn)積累,你會(huì)學(xué)會(huì)更精細(xì)的招式,比如改寫(xiě)SQL、利用執(zhí)行計(jì)劃、選擇合適的存儲(chǔ)結(jié)構(gòu)。
所以,下次面試官再問(wèn)你“如何優(yōu)化WHERE子句”,別慌。微微一笑,然后用今天學(xué)到的這套邏輯回答,保證能讓面試官眼前一亮!
END
那么,小伙伴們,你們?cè)诠ぷ髦杏袥](méi)有遇到過(guò) WHERE子句優(yōu)化的坑?比如寫(xiě)了個(gè)模糊查詢(xún)結(jié)果全表掃描?歡迎在評(píng)論區(qū)分享你的故事,我們一起探討!
我是小米,一個(gè)喜歡分享技術(shù)的31歲程序員。如果你喜歡我的文章,歡迎關(guān)注我的微信公眾號(hào)“軟件求生”,獲取更多技術(shù)干貨!
到此這篇關(guān)于MySQL數(shù)據(jù)庫(kù)社招必考題:索引如何優(yōu)化WHERE子句?的文章就介紹到這了,更多相關(guān)Mysql數(shù)據(jù)庫(kù)社招之WHERE優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
提升MySQL查詢(xún)效率及查詢(xún)速度優(yōu)化的四個(gè)方法詳析
查詢(xún)語(yǔ)句的優(yōu)化是提高M(jìn)ySQL查詢(xún)速度的重要方法,可以通過(guò)使用JOIN語(yǔ)句、子查詢(xún)、優(yōu)化where子句等方式來(lái)減少查詢(xún)的時(shí)間,下面這篇文章主要給大家介紹了關(guān)于提升MySQL查詢(xún)效率及查詢(xún)速度優(yōu)化的四個(gè)方法,需要的朋友可以參考下2023-04-04
mysql8 公用表表達(dá)式CTE的使用方法實(shí)例分析
這篇文章主要介紹了mysql8 公用表表達(dá)式CTE的使用方法,結(jié)合實(shí)例形式分析了mysql8 公用表表達(dá)式CTE的基本功能、原理使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2020-02-02
解決SQLyog連接MySQL出現(xiàn)錯(cuò)誤Plugin caching_sha2_password co
當(dāng)使用SQLyog連接MySQL時(shí),如果遇到插件caching_sha2_password無(wú)法加載的錯(cuò)誤,可以通過(guò)更改密碼并將其標(biāo)識(shí)為mysql_native_password來(lái)解決,具體步驟包括:打開(kāi)命令提示符窗口,登錄MySQL,修改密碼并更換插件,然后使用新密碼連接SQLyog2025-01-01
Mysql和SQLServer驅(qū)動(dòng)連接的實(shí)現(xiàn)步驟
本文主要介紹了Mysql和SQL?Server的驅(qū)動(dòng)連接,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
mysql 觸發(fā)器實(shí)現(xiàn)兩個(gè)表的數(shù)據(jù)同步
本文將介紹mysql 觸發(fā)器實(shí)現(xiàn)兩個(gè)表的數(shù)據(jù)同步,需要的朋友可以參考2012-11-11
mysql的case when字段為空,null的問(wèn)題
這篇文章主要介紹了mysql的case when字段為空,null的問(wèn)題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
MySQL百萬(wàn)級(jí)數(shù)據(jù)量分頁(yè)查詢(xún)方法及其優(yōu)化建議
這篇文章主要介紹了MySQL百萬(wàn)級(jí)數(shù)據(jù)量分頁(yè)查詢(xún)方法及其優(yōu)化建議,幫助大家更好的處理MySQL數(shù)據(jù)庫(kù),感興趣的朋友可以了解下2020-08-08

