-- 32 秒!
SELECT * FROM tables WHERE m_id IN (50,49) ORDER BY id DESC LIMIT 10;
-- 去掉 ORDER BY:0.05 秒
SELECT * FROM tables WHERE m_id IN (50,49) LIMIT 10;
原因:MySQL 先按 m_id 索引篩選,再對結果集檔案排序,最後 LIMIT。大 offset 時排序開銷巨大。
-- 建立複合索引
ALTER TABLE tables ADD INDEX idx_mid_id (m_id, id);
-- 強制使用索引
SELECT * FROM tables FORCE INDEX (idx_mid_id)
WHERE m_id IN (50,49) ORDER BY id DESC LIMIT 10;
(m_id, id) 排序,直接逆序掃描前 10 行,避免 filesort。-- 優化前:掃描 50 行丟棄 50 行
SELECT * FROM member ORDER BY last_active LIMIT 50, 5;
-- 優化後:子查詢只掃描索引取 ID,主查詢回表 5 行
SELECT * FROM member
INNER JOIN (
SELECT member_id FROM member ORDER BY last_active LIMIT 50, 5
) AS t USING (member_id);
Covering Index 僅讀索引,主查詢按主鍵精準回表。-- 首頁
SELECT * FROM tables WHERE m_id IN (50,49) ORDER BY id DESC LIMIT 20;
-- 翻頁:記住上一頁最小 id
SELECT * FROM tables WHERE m_id IN (50,49) AND id < 12345 ORDER BY id DESC LIMIT 20;
last_id(游標)。SELECT *,減少網路傳輸與記憶體。READ COMMITTED 或 REPEATABLE READ 配合一致性讀。WHERE 條件列在前,排序分組列在後,選取列覆蓋索引,深分頁不再愁。