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

MySQL COUNT(*) 效能深度解析:COUNT(*) vs COUNT(col)、WHERE 條件影響、優化三大鐵律

     編輯:MySQL 綜合教學

前言:COUNT 是最常用卻最易誤解的聚合函數

網上關於 COUNT(*) 與 COUNT(col) 效能的說法眾說紛紜。本文通過實測數據(7.9 萬行測試表),揭示 無 WHERE 時等價、有 WHERE 時 COUNT(*) 完勝 COUNT(col) 的鐵律,並給出生產環境優化三大原則。

實測數據對比(表 cdb_posts,fid=604 條件)

SQL耗時結果
SELECT COUNT(*) FROM cdb_posts WHERE fid = 604;0.03 秒79,000
SELECT COUNT(tid) FROM cdb_posts WHERE fid = 604;0.33 秒79,000
SELECT COUNT(pid) FROM cdb_posts WHERE fid = 604;0.33 秒79,000

結論:帶 WHERE 時,COUNT(*) **快 10 倍以上**。

原理深度解析

無 WHERE 條件:MyISAM 秒級、InnoDB 掃表

  • MyISAM:表元數據儲存精確行數,COUNT(*) 直接讀取元數據,O(1)
  • InnoDB:MVCC 導致可見行數隨事務變化,無法緩存精確值,**必須掃描聚簇索引/二級索引**,O(N)
  • 無 WHERE 時,COUNT(*)、COUNT(col)、COUNT(1) **執行計劃一致**,效能等價

有 WHERE 條件:索引覆蓋決定生死

  • COUNT(*):優化器傾向選擇**最小的二級索引**掃描(如單列索引),僅讀取索引葉子節點,極快
  • COUNT(col):若 col 無索引或非覆蓋索引,需**回表讀取聚簇索引**判斷 col IS NOT NULL,IO 放大 10 倍+
  • COUNT(1) / COUNT(*):語義完全等價,MySQL 內部統一重寫為 COUNT(*)

語義差異補充

函數統計對象NULL 處理
COUNT(*)行數包含 NULL 行
COUNT(col)該欄非 NULL 個數忽略 NULL
COUNT(DISTINCT col)該欄非 NULL 去重個數忽略 NULL

優化三大鐵律

  1. 任何情況下,首選 SELECT COUNT(*) FROM table:語義清晰、優化器最友好、執行計劃最優
  2. 極力減少 SELECT COUNT(*) FROM table WHERE col = 'val':若極高頻,考慮計數表(觸發器/應用層維護)、Redis 計數器、物化視圖異步刷新
  3. 杜絕 SELECT COUNT(col) FROM table WHERE col2 = 'val':除非 col 恰好在覆蓋索引中,否則必回表,效能災難

進階:大表精確計數替代方案

  • 近似值:EXPLAIN SELECT * FROM table 中 rows 欄位、information_schema.TABLES.TABLE_ROWS(InnoDB 為估算值)
  • 計數表:單獨表 table_counts(table_name, cnt),寫入時同步增減(注意事務一致性)
  • 分區表:按時間分區,歷史分區行數固化,僅計算熱分區
  • ClickHouse / Apache Doris:OLAP 引擎毫秒級精確計數

結語

COUNT(*) 非慢,慢在「無索引覆蓋的 WHERE」與「錯誤使用 COUNT(col)」。牢記「首選 COUNT(*)、WHERE 必上覆蓋索引、高頻計數異步化」三大原則,即可在生產環境游刃有餘。

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