首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 數據庫優化 8 大核心原則:從索引設計到 SQL 重寫

     編輯:MySQL 綜合教學

前言

MySQL 性能優化是系統穩定性的基石。本文提煉 8 大核心優化原則,涵蓋索引策略、SQL 重寫、架構設計,每條原則附帶反面教材與最佳實踐,助你構建高性能數據庫。

原則 1:創建索引——查詢加速的基石

核心觀點

無索引 = 全表掃描。大表無索引查詢是性能殺手。

反面教材

-- 1000 萬行表,無索引查詢耗時 5 秒+
SELECT * FROM orders WHERE user_id = 12345;

最佳實踐

  • 高選擇性列(唯一值多)優先建索引
  • WHERE、JOIN、ORDER BY、GROUP BY 涉及的列建索引
  • 避免過度索引:低選擇性列(如性別、狀態、是否刪除)建索引反而拖慢寫入

原則 2:復合索引——利用最左前綴特性

核心觀點

單列索引查詢只能用一個索引,復合索引可同時滿足多列過濾。

案例

-- 查詢:北京 22 歲用戶
SELECT * FROM users WHERE area = 'beijing' AND age = 22;

-- ❌ 單列索引:只能用 area 或 age 其中一個
-- ✅ 復合索引 (area, age):一次索引查找完成

-- 進階:(area, age, salary) 等價於三個索引
-- (area, age, salary) 、 (area, age) 、 (area)
-- 這就是「最左前綴特性」

設計規範

  1. 最常用作過濾條件的列放最左
  2. 區分度高的列放最左
  3. 頻繁排序的列放在 WHERE 列之後

原則 3:索引不包含 NULL 值

核心觀點

單列索引不存 NULL;復合索引任一列為 NULL,該行不進入索引。

最佳實踐

  • 表設計階段:所有列默認 NOT NULL
  • 業務無意義時用默認值(0、空字符串、'1970-01-01')代替 NULL
  • 已有 NULL 列需查詢:考慮 WHERE col IS NULL 無法用索引,改用 WHERE col = '' 或增加虛擬列

原則 4:使用短索引(前綴索引)

核心觀點

長字符串列(VARCHAR(255)、TEXT、BLOB)建全列索引佔用空間大、I/O 高。

實戰

-- 假設 email 前 20 字符區分度已 > 90%
ALTER TABLE users ADD INDEX idx_email_prefix (email(20));

收益

  • 索引體積縮小 50%+
  • 查詢速度提升(更多索引頁面進內存)
  • INSERT/UPDATE 維護開銷降低

原則 5:排序與索引的關係

核心觀點

MySQL 單表查詢只能使用一個索引。WHERE 用了索引,ORDER BY 就無法再用索引。

策略

原則 6:LIKE 語句優化

核心觀點

LIKE '%keyword%' 不走索引(全表掃描);LIKE 'keyword%' 可走索引(前綴匹配)。

優化方案

  • 業務允許時,改為前綴匹配
  • 全文搜索需求:使用 全文索引(MyISAM 5.6+、InnoDB 5.6.4+)或 Elasticsearch
  • 前綴固定長度:LIKE 'abc%' 走索引,LIKE '%abc' 不走

原則 7:不要在索引列上進行運算

核心觀點

列上加函數/運算/類型轉換 → 索引失效 → 全表掃描。

反面教材 vs 最佳實踐

場景建議
WHERE + ORDER BY 同列單列索引即可
WHERE 列 + ORDER BY 列不同建立復合索引 (where_col, order_col)
多列排序建立復合索引匹配排序順序
無 WHERE 純排序索引可用於排序(如 idx_created_at)
❌ 悪例(索引失效)✅ 佳例(索引生效)
WHERE YEAR(create_time) = 2024WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01'
WHERE DATE_FORMAT(t, '%Y-%m') = '2024-01'WHERE t >= '2024-01-01' AND t < '2024-02-01'
WHERE SUBSTRING(phone, 1, 3) = '138'WHERE phone LIKE '138%'
WHERE id + 1 = 100WHERE id = 99
WHERE UPPER(name) = 'JOHN'WHERE name = 'JOHN' (或建函數索引 8.0+)

原則 8:避免 NOT IN 和 <> 操作

核心觀點

NOT IN、<>、!= 通常導致全表掃描,不走索引。

改寫方案

原寫法改寫原理
WHERE id NOT IN (1,2,3)WHERE id NOT EXISTS (SELECT 1 FROM t2 WHERE t2.id = t1.id AND t2.id IN (1,2,3))NOT EXISTS 可用索引
WHERE status <> 1WHERE status = 0 OR status = 2IN/OR 可用索引合併
WHERE id != 3WHERE id > 3 OR id < 3範圍查詢可用索引

優化檢查清單(上線前自查)

□ 所有查詢 EXPLAIN 過,無 ALL、無 Using temporary、無 Using filesort
□ 高頻 SQL 都有對應索引(含復合索引最左前綴)
□ 無 SELECT *,按需選列(減少網絡、內存、覆蓋索引機會)
□ 大表有歸檔/分區策略
□ 寫入峰值評估過,innodb_buffer_pool_size 設為內存 70-80%
□ 慢查詢日志開啟,long_query_time = 1s
□ 定期 ANALYZE TABLE 更新統計信息
□ 備份恢復演練每季度一次

總結

MySQL 優化無銀彈,但遵循這 8 大原則能解決 80%+ 性能問題:索引是核心武器,SQL 重寫是戰術手段,架構設計是戰略保障。建立「慢查詢→分析→優化→驗證」閉環,讓數據庫性能持續在線。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved