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

MySQL 統計表行數的 3 種方法:COUNT(*)、COUNT(1)、COUNT(col) 效能真相

     編輯:MySQL 綜合教學

MySQL 統計表行數的 3 種方法:COUNT(*)、COUNT(1)、COUNT(col) 效能真相

統計表行數是最常見的查詢,但 COUNT(*)、COUNT(1)、COUNT(col) 效能是否有差異?本文揭示真相並給出最佳實踐。

語法與語意差異

寫法語意NULL 處理
COUNT(*)統計**行數**包含 NULL 行
COUNT(1)統計常數 1 的非 NULL 個數(等同 COUNT(*))包含 NULL 行
COUNT(col)統計該欄位**非 NULL 值**個數**忽略 NULL**

效能真相

-- MySQL 8.0.13+ 優化器將 COUNT(*) 和 COUNT(1) 視為完全等價
EXPLAIN SELECT COUNT(*) FROM `large_table`;
EXPLAIN SELECT COUNT(1) FROM `large_table`;
-- 兩者執行計劃相同:type=index, key=PRIMARY (或最小二級索引), rows=N

-- COUNT(col) 若該欄位有索引,同樣走索引掃描
-- 若無索引,全表掃描,效能同 COUNT(*)

結論:

  • InnoDB:COUNT(*)、COUNT(1) **完全等價**,優化器會選擇最小索引掃描(通常是主鍵或最小二級索引),不讀取資料行。
  • COUNT(col) 語意不同(排除 NULL),**不可隨意替換**。
  • 無 WHERE 條件時,MyISAM 直接返回儲存的行數(O(1)),InnoDB 需掃描索引(O(N))。

大表統計行數優化方案

方案適用場景優點缺點
近似值:SHOW TABLE STATUS / information_schema.TABLES不需精確、監控大屏極快 (O(1))非即時、有誤差(InnoDB 統計資訊更新延遲)
觸發器維護計數表需精確、高頻查詢查詢 O(1)、精確寫入開銷、鎖競爭、複雜度高
Redis 快取行數高併發讀、允許秒級延遲極快、卸載 DB一致性維護、冷啟動預熱
定時任務統計存表報表、分析不影響線上非即時

實戰建議

  1. **預設用 COUNT(*)**,語意清晰、優化器最優。
  2. 帶 WHERE 條件時,確保條件欄位有索引,避免全表掃描。
  3. 避免 SELECT COUNT(*) FROM t1 JOIN t2 ... 統計關聯結果,改用應用層分頁計數或觸發器維護。
  4. 監控儀表板用 information_schema.TABLES.TABLE_ROWS 近似值,標註「約」。

驗證 COUNT(*) vs COUNT(1) 執行計劃

mysql> EXPLAIN SELECT COUNT(*) FROM `emp`;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1  | SIMPLE      | emp   | NULL       | index | NULL          | PRIMARY | 4       | NULL | 15   | 100.00   | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

mysql> EXPLAIN SELECT COUNT(1) FROM `emp`;
-- 相同輸出
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved