MySQL 能否利用索引優化 DISTINCT 取決於**索引是否有序**。
DISTINCT 掃描(Using index for group-by / Using index)DISTINCT,只能全表掃描 + 臨時表CREATE TABLE m11 (a INT PRIMARY KEY, b INT, c INT, d INT) ENGINE=InnoDB;
EXPLAIN SELECT DISTINCT a FROM m11;
-- type=index, key=PRIMARY, Extra=Using index ✅ 走索引
CREATE TABLE m31 (a INT PRIMARY KEY, b INT, c INT, d INT) ENGINE=MEMORY;
EXPLAIN SELECT DISTINCT a FROM m31;
-- type=ALL, key=NULL, Extra=NULL ❌ 全表掃描,Hash 索引無序
CREATE TABLE m33 (a INT, b INT, c INT, d INT, INDEX USING BTREE (a)) ENGINE=MEMORY;
EXPLAIN SELECT DISTINCT a FROM m33;
-- type=index, key=a, Extra=NULL ✅ 走 B-Tree 索引
USING BTREE**key=NULL 且 type=ALL 即索引失效SELECT DISTINCT col1, col2 要求聯合索引 (col1, col2) 順序一致方可走索引。
-- 錯誤:DISTINCT 只能跟單列?實際可跟多列,但結果是「多列組合去重」
SELECT DISTINCT title, posttime FROM table; -- 正確語法,返回 (title,posttime) 唯一組合
-- 方案 1:子查詢取最小主鍵 (通用、可走索引)
SELECT t.* FROM table t
JOIN (SELECT MIN(id) AS id FROM table GROUP BY title) tmp USING (id);
-- 方案 2:GROUP BY 多列 (若需保留 posttime 組合)
SELECT title, posttime FROM table GROUP BY title, posttime;
-- 方案 3:窗口函數 (MySQL 8.0+,最靈活)
SELECT title, posttime, content FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY title ORDER BY id) rn
FROM table
) t WHERE rn = 1;
Using index for group-by 或 Using indexSELECT DISTINCT * 導致臨時表過寬索引類型是 DISTINCT 性能的分水嶺:**B-Tree 讓去重成為索引掃描,Hash 讓去重淪為全表掃描**。