相同查詢重複執行時,快取命中極快。但含非確定性函數會失效:
-- 失效
SELECT * FROM user WHERE signup_date >= CURDATE();
-- 生效
$today = date("Y-m-d");
SELECT * FROM user WHERE signup_date >= '$today';
檢視索引使用、掃描行數、連接類型。案例:缺少 group_id 索引導致全表掃描,加上後 rows 從幾萬降為 1。
-- 低效
SELECT * FROM user WHERE state = 'Alabama';
-- 高效
SELECT 1 FROM user WHERE state = 'Alabama' LIMIT 1;
引擎找到第一筆即停止掃描。
任何出現在 WHERE/JOIN 的欄位皆應評估建立索引。
-- 錯誤:DECIMAL JOIN INT,字符集不一
LEFT JOIN companies ON (users.state = companies.state)
類型不符或編碼不同會導致隱式轉換,索引失效、全表掃描。
-- 極差:全表計算隨機值排序
SELECT username FROM user ORDER BY RAND() LIMIT 1;
-- 優化:應用層取隨機 offset
$count = SELECT COUNT(*) FROM user;
$rand = mt_rand(0, $count-1);
SELECT username FROM user LIMIT $rand, 1;
-- 差
SELECT * FROM user WHERE user_id = 1;
-- 好
SELECT username FROM user WHERE user_id = 1;
減少網路傳輸、磁碟 I/O、記憶體佔用,大結果集差異顯著。
根據現有資料分析建議最佳欄位類型、長度、是否 NOT NULL 等。
$stmt = $mysqli->prepare("SELECT username FROM user WHERE state=?");
$stmt->bind_param("s", $state);
$stmt->execute();
$stmt->bind_result($username);
$stmt->fetch();
優點:防 SQL 注入、重複執行解析優化、二進制協議傳輸效率高。
-- 存入
UPDATE users SET ip = INET_ATON('192.168.1.1') WHERE user_id = 1;
-- 讀出
SELECT INET_NTOA(ip) FROM users;
僅佔 4 字節,比 VARCHAR(15) 省空間、比較更快、支援範圍查詢。