首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 索引優化 DISTINCT 實戰:索引類型陷阱與多列去重解決方案

     編輯:MySQL 綜合教學

核心結論:索引類型決定 DISTINCT 能否走索引

MySQL 能否利用索引優化 DISTINCT 取決於**索引是否有序**。

  • B-Tree 索引:有序 → 支持 DISTINCT 掃描(Using index for group-by / Using index)
  • Hash 索引:無序 → **不支持** DISTINCT,只能全表掃描 + 臨時表

實驗驗證

表 m11 (InnoDB, 主鍵 B-Tree)

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  ✅ 走索引

表 m31 (MEMORY, 主鍵默認 Hash)

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 索引無序

表 m33 (MEMORY, 顯式指定 B-Tree)

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 索引

避坑指南

  1. MEMORY 引擎默認 Hash 索引 → 任何需排序/範圍/去重的查詢**必須顯式指定 USING BTREE**
  2. 查看 EXPLAIN 的 key 與 Extra**:key=NULL 且 type=ALL 即索引失效
  3. InnoDB 主鍵/二級索引均為 B-Tree**,無此問題

多列 DISTINCT 解決方案

SELECT DISTINCT col1, col2 要求聯合索引 (col1, col2) 順序一致方可走索引。

常見錯誤寫法

-- 錯誤:DISTINCT 只能跟單列?實際可跟多列,但結果是「多列組合去重」
SELECT DISTINCT title, posttime FROM table;  -- 正確語法,返回 (title,posttime) 唯一組合

業務常見需求:「按 title 去重,保留每組第一行的其他列」

-- 方案 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;

優化檢查清單

  • [ ] 去重列上有 B-Tree 索引(單列或聯合索引順序匹配)
  • [ ] EXPLAIN 顯示 Using index for group-by 或 Using index
  • [ ] 避免 SELECT DISTINCT * 導致臨時表過寬
  • [ ] 大表考慮分區裁剪或應用層分批去重
  • [ ] MEMORY 表檢查索引類型是否為 BTREE

索引類型是 DISTINCT 性能的分水嶺:**B-Tree 讓去重成為索引掃描,Hash 讓去重淪為全表掃描**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved