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

MySQL COUNT(*) 與 DISTINCT 效能深度解析

     編輯:MySQL 綜合教學

COUNT(*) 兩種場景的巨大差異

場景一:全表計數(無 WHERE)

SELECT COUNT(*) FROM tablename;
  • MyISAM:極快(O(1)),引擎維護精確行數計數器。
  • InnoDB:需全表掃描(MVCC 導致無統一計數器),但 8.0+ 有並行掃描優化。
  • 建議:頻繁全表計數可維護一張計數表,或用 Redis 快取。

場景二:帶條件計數

SELECT COUNT(*) FROM tablename WHERE status = 1;
  • 必須掃描符合條件的列(利用索引可大幅加速)。
  • 確保 WHERE 條件欄位有索引。

DISTINCT 進階用法與陷阱

1. 計算不重複值個數

SELECT COUNT(DISTINCT id) FROM tablename;

2. 返回不重複值列表

SELECT DISTINCT id FROM tablename;

3. 多欄位 DISTINCT 的常見誤區

SELECT DISTINCT id, type FROM tablename;

結果:(id, type) 組合去重,而非單獨 id 去重。若期望「每個 id 只取一列」,此寫法錯誤。

4. 解決「單欄去重但需帶出其他欄位」

方案 A:GROUP_CONCAT (MySQL 4.1+)

SELECT id, GROUP_CONCAT(type) AS types
FROM tablename
GROUP BY id;

方案 B:聚合函數 + GROUP BY

SELECT id, type, COUNT(DISTINCT id) AS cnt
FROM tablename
GROUP BY id, type;

返回 id 唯一的所有組合,附帶計數欄位(可忽略)。

方案 C:視窗函數 (MySQL 8.0+)

SELECT id, type
FROM (
    SELECT id, type, ROW_NUMBER() OVER (PARTITION BY id ORDER BY type) AS rn
    FROM tablename
) t
WHERE rn = 1;

最標準、語意最清晰,效能亦佳。

效能優化總結

場景建議
MyISAM 全表 COUNT(*)極快,直接用
InnoDB 全表 COUNT(*)避免高頻呼叫;維護計數表或快取
帶 WHERE COUNT(*)確保條件欄位有索引
COUNT(DISTINCT col)大表慎用;可考慮 HyperLogLog 近似計數
單欄去重帶其他欄位MySQL 8.0+ 用 ROW_NUMBER();舊版用 GROUP BY + 聚合
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved