SELECT COUNT(*) FROM table_name
是個再常見不過的統計需求了。
本文帶你瞭解下Mysql
的COUNT
函數。php
COUNT
函數關於COUNT
函數,在MySQL
官網中有詳細介紹:html
翻譯一下:mysql
COUNT(expr)
,返回SELECT
語句檢索的行中expr
的值不爲NULL
的數量,結果是一個BIGINT
值。0
COUNT(*)
的統計結果中,會包含值爲NULL
的行數。在《阿里巴巴Java開發手冊》也有以下要求:git
COUNT(列名)
、COUNT(常量)
和COUNT(*)
前面咱們提到過
COUNT(expr)
用於作行數統計,那麼COUNT(列名)
、COUNT(常量)
和COUNT(*)
這三種語法中,expr
分別是列名、 常量 和*
。github
COUNT(*)
和COUNT(常量)
在列名、常量和*
這三個條件中,常量是一個固定值,確定不爲NULL
。*
能夠理解爲查詢整行,因此確定也不爲NULL
,那麼就只有列名的查詢結果多是NULL
。sql
因此, COUNT(常量)
和 COUNT(*)
表示的是直接查詢符合條件的數據庫表的行數。而COUNT(列名)
表示的是查詢符合條件的列的值不爲NULL
的行數。數據庫
COUNT(*)
和COUNT(1)
區別COUNT(1)
就是COUNT(常量)
,對於這兩者到底有沒有區別:緩存
COUNT(*)
執行時會轉換成COUNT(1)
,因此COUNT(1)
少了轉換步驟,因此更快。MySQL
針對COUNT(*)
作了特殊優化,因此COUNT(*)
更快。到底哪一種說法是對的?看下MySQL
官方文檔:函數
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
經過文檔,對於COUNT(1)
和COUNT(*)
,MySQL
的優化是徹底同樣的,根本不存在誰比誰快!post
COUNT(列名)
相較於前二者,COUNT(列名)
的查詢就比較簡單粗暴了,就是進行全表掃描,而後判斷指定字段的值是否是爲NULL
,不爲NULL
則累加。
相比
COUNT(*)
,COUNT(列名)
多了一個步驟就是判斷所查詢的字段是否爲NULL
,因此他的性能要比COUNT(*)
慢。
here和group的條件查詢。
SQL92
除了查詢獲得結果集有區別以外,COUNT(*)
相比COUNT(常量)
和 COUNT(列名)
來說,COUNT(*)
是SQL92
定義的標準統計行數的語法,由於他是標準語法,因此MySQL
數據庫對他進行過不少優化。
SQL92
,是數據庫的一個ANSI/ISO
標準。它定義了一種語言(SQL
)以及數據庫的行爲(事務、隔離級別等)。
COUNT(*)
優化由於COUNT(*)
是SQL92
定義的標準統計行數的語法,因此MySQ
L對其進行了不少優化:
MyISAM
中會直接把表的總行數單獨記錄下來供COUNT(*)
查詢InnoDB
會在掃表的時候選擇最小的索引來下降成本。這些優化的前提都是沒有進行
where
和group
的條件查詢,更多請參考MySQL 全表 COUNT(*) 簡述
COUNT
函數用於統計表行數,按照效率比較的話:
count(*)=count(常量)>count(列名)
既然 count(*)
在查詢上依賴於全部的數據集,因此咱們在設計上也須要儘可能的規避全量 count
。
一般狀況咱們針對可預見的 count
查詢會作適當的緩存,能夠是 Redis
,也能夠是獨立的 MySQL
count
表。