MySQL 查詢優(yōu)化是提升數據庫性能的關鍵,主要目標是減少執(zhí)行時間、降低資源消耗。以下是常見的優(yōu)化策略和實踐方法:
索引是提升查詢效率的核心,合理的索引能大幅減少數據掃描量。
-
頻繁作為查詢條件的列(
WHERE、JOIN、ON 后的列)
-
排序 / 分組的列(
ORDER BY、GROUP BY 后的列)
-
聯(lián)合索引:多條件查詢時,按 “最左前綴原則” 創(chuàng)建聯(lián)合索引(如
WHERE a=? AND b=? 可建 (a,b) 索引)
-
不建索引:
-
表數據量極。ㄈ鐜装傩校
-
頻繁更新的列(索引會增加寫入開銷)
-
低基數列(如性別、狀態(tài)只有幾個值的列)
-
避免重復索引(如同時建
(a) 和 (a,b) 索引,前者冗余)
-
刪除長期未使用的索引(可通過
sys.schema_unused_indexes 查看)
-
使用函數或運算操作索引列(如
WHERE SUBSTR(name,1,3)='abc')
-
隱式類型轉換(如字符串列用數字查詢
WHERE phone=13800138000)
-
WHERE 子句中用 NOT、!=、<>、NOT IN 等可能導致全表掃描
-
LIKE 以通配符開頭(如 WHERE name LIKE '%abc')
-
確保查詢條件能命中索引(用
EXPLAIN 分析執(zhí)行計劃)
-
不寫無
WHERE 條件的全表查詢(如 SELECT * FROM large_table)
-
只查詢需要的列,避免
SELECT *(減少數據傳輸和內存消耗)
SELECT * FROM users WHERE age > 30;
SELECT id, name FROM users WHERE age > 30;
-
小表驅動大表(
JOIN 時,將數據量小的表作為驅動表)
-
確保
JOIN 條件列有索引(如 a JOIN b ON a.id = b.a_id,需在 b.a_id 建索引)
-
避免
JOIN 過多表(建議不超過 5 張表,否則考慮分拆查詢)
-
復雜子查詢改用
JOIN(子查詢可能產生臨時表,性能較差)
SELECT name FROM users WHERE id IN (SELECT user_id FROM orders WHERE status=1);
SELECT u.name FROM users u JOIN orders o ON u.id = o.user_id WHERE o.status=1;
-
ORDER BY/GROUP BY 的列盡量包含在索引中(避免額外排序)
-
避免
SELECT DISTINCT(可用 GROUP BY 替代,或通過索引優(yōu)化)
EXPLAIN 是優(yōu)化的核心工具,可查看查詢的執(zhí)行方式(是否用索引、掃描行數等)。
EXPLAIN SELECT id, name FROM users WHERE age > 30;
-
type:訪問類型,性能從好到差為 system > const > eq_ref > ref > range > index > ALL(目標是至少達到 range 或 ref)
-
key:實際使用的索引(NULL 表示未用索引)
-
rows:預估掃描行數(值越小越好)
-
Extra:額外信息(如 Using index 表示覆蓋索引,Using filesort 表示需要額外排序,需優(yōu)化)
-
優(yōu)先用小類型(如
INT 替代 BIGINT,VARCHAR(20) 替代 VARCHAR(255))
-
時間用
DATETIME 或 TIMESTAMP(而非字符串)
-
枚舉值用
ENUM 類型(如性別、狀態(tài))
-
垂直拆分:將大表按字段關聯(lián)性拆分為小表(如用戶表拆分為
user_base 和 user_detail)
-
水平拆分:按規(guī)則拆分數據(如按時間分表
orders_2023、orders_2024,按用戶 ID 哈希分表)
-
盡量用默認值替代
NULL(如用 0 表示數量,'' 表示空字符串),NULL 會增加索引和查詢復雜度。
-
用
LIMIT 限制返回行數(尤其分頁查詢)
SELECT * FROM articles WHERE id > 100000 LIMIT 10;
-
調整
my.cnf/my.ini 參數:
-
innodb_buffer_pool_size:InnoDB 緩存池(建議設為物理內存的 50%-70%)
-
query_cache_size:查詢緩存(MySQL 8.0 已移除,低版本按需開啟)
-
max_connections:最大連接數(避免連接耗盡)
-
分析表:
ANALYZE TABLE 表名;(更新索引統(tǒng)計信息,幫助優(yōu)化器生成更好的執(zhí)行計劃)
-
優(yōu)化表:
OPTIMIZE TABLE 表名;(回收碎片,適用于頻繁刪除 / 更新的表)
-
長事務拆分為短事務(減少鎖持有時間)
-
批量操作分批次執(zhí)行(如一次更新 1000 行,而非 100 萬行)
查詢優(yōu)化的核心思路是:減少數據掃描量(通過索引)、減少數據傳輸量(按需查詢)、減少資源競爭(優(yōu)化事務和鎖)。實際優(yōu)化中,需結合業(yè)務場景,先用 EXPLAIN 定位瓶頸,再針對性調整索引、SQL 或表結構。