爲什麼要學查詢優化?
想象一下,當你寫了一條SQL查詢,點擊執行後卻要等十幾秒頁面才加載出來——這時候用戶可能已經放棄了。查詢優化的核心目標就是讓SQL更快執行,減少數據庫負載,提升整個系統的響應速度。對初學者來說,掌握一些基礎技巧,就能顯著改善查詢效率,避免“簡單問題複雜化”。

一、新手最容易犯的3個查詢錯誤

在優化之前,先看看你是否踩過這些坑:
1. 全表掃描:沒加索引,讓數據庫從頭遍歷整個表(比如查詢SELECT * FROM users WHERE name='小明',而name是大表的字段且無索引)。
2. SELECT :一次性取所有字段,導致大量不必要的數據傳輸和內存佔用。
3.
濫用JOIN或複雜條件*:JOIN太多表、或在WHERE裏用函數包裹索引字段(比如YEAR(create_time)=2023)。

二、5個必學的簡單優化技巧

技巧1:給查詢條件加索引(避免全表掃描)

問題:如果查詢條件字段沒有索引,數據庫會“逐個檢查”表中每一行,這就是“全表掃描”,數據量大時極其緩慢。
解決:給高頻查詢的字段加索引。
舉例

-- 未優化:全表掃描(假設users表有10萬行,name無索引)
SELECT * FROM users WHERE name='小明';  

-- 優化:給name加索引(執行一次,後續查詢受益)
CREATE INDEX idx_name ON users(name);  
-- 優化後:數據庫直接通過索引定位數據,type從ALL變爲ref(EXPLAIN可驗證)

注意
- 索引不是越多越好!寫得越多,插入/更新/刪除時維護索引的成本越高(比如用戶表的id主鍵默認有索引,無需重複建)。
- 優先給“重複值少、查詢條件多”的字段加索引(如user_idusername(可能重名)更合適)。

技巧2:避免SELECT *,只取需要的字段

問題SELECT *會返回表中所有字段,包括大字段(如text類型),導致IO效率極低。
解決:明確列出需要的字段。
舉例

-- 錯誤:返回所有字段,包含大文本等冗餘數據
SELECT * FROM orders;  

-- 優化:只取核心字段(如id、order_no、amount)
SELECT id, order_no, amount FROM orders;  

效果:數據量越大,SELECT *的劣勢越明顯,減少字段能直接降低網絡傳輸和內存佔用。

技巧3:優化JOIN操作:小表驅動大表

問題:JOIN多個表時,表的連接順序錯誤會導致“大表被全表掃描”。
解決用小表驅動大表(先過濾小表,再關聯大表),且優先用INNER JOIN(只保留匹配的數據)。
舉例

-- 錯誤:大表orders在前,先全表掃描大表,再關聯小表order_items
SELECT o.id, oi.product_id FROM orders o LEFT JOIN order_items oi ON o.id=oi.order_id WHERE o.status='已完成';  

-- 優化:先過濾orders小表(假設status='已完成'的數據少),再關聯order_items大表
SELECT o.id, oi.product_id FROM 
  (SELECT id FROM orders WHERE status='已完成') o  -- 小表
  LEFT JOIN order_items oi ON o.id=oi.order_id;    -- 再關聯大表

原理:數據庫JOIN時會以“左表”爲基準,小表數據少,遍歷次數更少,效率更高。

技巧4:別在索引字段上用函數

問題:在WHERE條件中對索引字段用函數(如YEAR()DATE()),會導致索引失效,重新全表掃描。
錯誤舉例

SELECT * FROM sales WHERE YEAR(sale_date)=2023;  -- sale_date的索引被YEAR()函數“破壞”

解決:把函數邏輯移到字段本身,避免索引失效。
優化後

-- 用BETWEEN代替函數,讓索引生效
SELECT * FROM sales WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31';  

技巧5:用EXPLAIN分析查詢計劃(關鍵!)

新手必學工具EXPLAIN能幫你“看穿”SQL執行過程,快速定位問題。執行EXPLAIN + SQL,看輸出的type列和Extra列:
- type列ALL(全表掃描,差!改!)、ref(走索引,優)、eq_ref(主鍵關聯,最好)。
- Extra列Using filesort(排序無索引)、Using temporary(創建臨時表)—— 遇到這些要警惕!

舉例

EXPLAIN SELECT * FROM users WHERE name='小明';  

如果typeALL,說明全表掃描;如果是ref,說明索引生效,查詢快。

三、3個常見誤區(避開就能少踩坑)

  1. 誤區1:索引越多越好
    索引會加速查詢,但會拖慢插入/更新/刪除。比如給users表的status(只有“0/1/2”三個值)建索引,反而讓每次更新都要維護索引,得不償失。

  2. 誤區2:OR條件導致索引失效
    OR連接條件時,可能無法同時走多個索引。例如:

   SELECT * FROM users WHERE id=1 OR name='張三';  -- 可能無法用id的索引

替代方案:用UNION ALL拆分條件(如果兩個字段的索引可以獨立使用):

   (SELECT * FROM users WHERE id=1) UNION ALL (SELECT * FROM users WHERE name='張三');  
  1. 誤區3:COUNT(*) = 快
    COUNT(*)統計行數很快(MySQL會直接走索引計數),但COUNT(DISTINCT name)會慢(需去重)。如果不需要去重,用COUNT(1)COUNT(*)即可。

四、總結:從小技巧開始,逐步優化

  1. 先查再優化:用EXPLAIN定位全表掃描、索引失效等問題。
  2. 基礎技巧優先:加索引、SELECT指定字段、優化JOIN順序。
  3. 避免重複造輪子:網上已有很多優化案例,遇到問題多搜“EXPLAIN分析”“索引失效”等關鍵詞。

記住:查詢優化不是“玄學”,而是基於“減少數據處理量+合理利用索引”的科學方法。掌握這些基礎技巧,你就能寫出“一看就快”的SQL啦!

小夜