program_access_log,4000 萬行,~30GBid,索引:program_id
-- 慢
SELECT * FROM program_access_log WHERE program_id BETWEEN 1 AND 4000;
-- 加 id 限制仍慢
SELECT * FROM program_access_log
WHERE id BETWEEN 1 AND 500000
AND program_id BETWEEN 1 AND 4000;
program_id 範圍小(選擇性高),優化器選它做驅動索引。id,需逐個回主鍵聚簇索引讀取完整行。| 方案 | 原理 | 優點 | 缺點 | 適用性 |
|---|---|---|---|---|
| 分區表 | 按 program_id 分區,裁剪掃描範圍 | 邏輯透明、維護簡單 | 5.0 不支援、5.1+ 才有 | 版本受限 |
| 分表 | 業務拆分多張小表 | 單表小、全載入記憶體 | 應用改造大、跨表查詢複雜 | 架構允許時 |
| 反向利用優化器 | 擴大 program_id 範圍,迫使走 id 索引 | 零改造、立竿見影 | 語意繞彎、需確保 id 連續 | 緊急止血 |
-- 擴大 program_id 範圍遠超 id 範圍
SELECT * FROM program_access_log
WHERE id BETWEEN 1 AND 500000
AND program_id BETWEEN 1 AND 15000000;
id 範圍更小(選擇性更高),選主鍵索引ALTER TABLE ADD INDEX idx_pid_id (program_id, id); 查詢只需 id, program_id 時可避免回表。innodb_buffer_pool_size 設至實體記憶體 70-80%,盡量缓住熱數據。「索引不是銀彈。優化器基於統計資訊選擇索引,統計失真或極端數據分佈會導致錯誤選擇。大表隨機 I/O 是效能殺手,**順序掃描優於隨機回表**。」
工具箱:EXPLAIN、ANALYZE TABLE、OPTIMIZE TABLE、SHOW ENGINE INNODB STATUS、perf_schema、sys.schema_table_statistics。