在面試的時候咱們會常常遇到這個問題:html
MySQL 中,COUNT(*)、COUNT(1)、COUNT(col) 有區別嗎?mysql
有區別。面試
接下來咱們分析一下這三者有什麼樣的區別。sql
從語義角度看,它們有不一樣的含義。併發
COUNT(
返回查詢到的行中 expr is not-NULL 的個數,返回類型爲 BIGINT(8 bytes)。expr
)
性能
Returns a count of the number of non-
NULL
values ofexpr
in the rows retrieved by aSELECT
statement. The result is aBIGINT
value.優化
COUNT(*) 有點不一樣,它返回查詢到的結果集中的行的個數,不論這些行是否含有 NULL 值。spa
COUNT(*)
is somewhat different in that it returns a count of the number of rows retrieved, whether or not they containNULL
values.rest
COUNT(1) 返回查詢到的行中第一列 not NULL 的個數。code
COUNT(col) 返回查詢到的行中 col 列中 not NULL 的個數。
在 MySQL 中討論查詢性能時,咱們須要區分存儲引擎。
不一樣的存儲引擎以不一樣的方式存儲數據,這決定了最終的操做效率。
MyISAM 的主鍵、輔助索引都是非聚簇索引,B+樹的葉節點包含的是數據的地址。
InnoDB 的主鍵是聚簇索引,葉節點存放的是數據自己;輔助索引是非聚簇索引,葉節點存放的是主鍵。
MyISAM 爲每張表存儲了一個準確(exact)的 row count。
所以,MyISAM 能夠爲 COUNT(*) 提供查詢優化:當某個 SELECT 語句僅僅查詢一張表、不查詢其餘列、沒有查詢條件(WHERE 子句)時,COUNT(*) 能夠很快地返回這個 row count(e.g. SELECT COUNT(*) FROM tbl_name)。
當第一列定義爲 NOT NULL 時,COUNT(1) 和 COUNT(*) 具備相同的查詢性能。
InnoDB 是一款 transactional 存儲引擎。
可能有多個事務併發操做一張表,因此 InnoDB 沒法爲每張表存儲一個準確的 row count(由於不一樣的 transaction 可能會看到不一樣的 row count,row count 很難準確)。
對於 InnoDB 而言,COUNT(*)、 COUNT(1) 沒有性能上的差別。
COUNT(*) 會利用索引:在 MySQL 5.7.18 以前,會利用聚簇索引;在 MySQL 5.7.18 以後,會利用一個最小的輔助索引(有的話)。