萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL 效能優化十大實戰技巧:查詢緩存、EXPLAIN、LIMIT 1、覆蓋索引與 IP 整數存儲

1. 善用查詢緩存

MySQL 會緩存完全相同的 SELECT 結果。**含非確定性函數(NOW()、RAND()、CURDATE())的查詢不會被緩存**。

-- 不走緩存
SELECT * FROM user WHERE signup_date >= CURDATE();

-- 走緩存:應用層計算日期字串
$today = date('Y-m-d');
$stmt = $pdo->prepare("SELECT * FROM user WHERE signup_date >= ?");
$stmt->execute([$today]);

2. 用 EXPLAIN 看透執行計畫

EXPLAIN SELECT ... 顯示 type(連接類型)、key(實際索引)、rows(預估掃描行)、Extra(Using filesort/Using temporary = 慢)。

案例:忘記在 group_id 建索引導致 type=ALL,加上索引後變 ref,rows 從幾萬降至個位數。

3. 只需存在性檢查用 LIMIT 1

-- 慢:掃描全表/索引
SELECT * FROM user WHERE state = 'Alabama';

-- 快:找到第一筆即停止
SELECT 1 FROM user WHERE state = 'Alabama' LIMIT 1;

4. 為搜尋欄位建立索引

不僅主鍵/唯一鍵,WHERE、JOIN、ORDER BY、GROUP BY 涉及的欄位都應評估建索引。

5. 關聯欄位型別、編碼、長度完全一致

JOIN ON a.col = b.col 時,a.col、b.col 必須同型別(INT vs INT)、同字元集(utf8 vs utf8)、同長度,否則隱性轉換導致索引失效、全表掃描。

6. 禁用 ORDER BY RAND()

每行計算隨機數、排序、再取一行,複雜度 O(N log N)。

替代方案:

$count = $pdo->query("SELECT COUNT(*) FROM user")->fetchColumn();
$offset = mt_rand(0, $count - 1);
$pdo->query("SELECT username FROM user LIMIT $offset, 1");

7. 明確列出欄位,拒絕 SELECT *

  • 減少網路傳輸、記憶體佔用、磁碟 IO。
  • 利用覆蓋索引(Using index)避免回表。

8. 用 PROCEDURE ANALYSE() 獲取結構建議

SELECT * FROM table_name PROCEDURE ANALYSE();

依現有資料分布建議最優型別(如 ENUM 替代 VARCHAR、INT UNSIGNED 等)。

9. 全面採用預備語句

  • 安全:驅動層自動參數綁定,徹底防注入。
  • 效能:重複執行同結構 SQL 只解析優化一次。
$stmt = $mysqli->prepare("SELECT username FROM user WHERE state = ?");
$stmt->bind_param("s", $state);
$stmt->execute();
$stmt->bind_result($username);
$stmt->fetch();

10. IP 位址存為 UNSIGNED INT

VARCHAR(15) 佔 15+ 位元組、字串比較慢。
INT UNSIGNED 固定 4 位元組、數值比較極快。

-- 寫入
UPDATE users SET ip = INET_ATON('192.168.1.1') WHERE id = 1;
-- 讀取
SELECT INET_NTOA(ip) FROM users WHERE id = 1;
copyright © 萬盛學電腦網 all rights reserved