SELECT COUNT(*) FROM table_name是個(gè)再常見(jiàn)不過(guò)的統計需求了。
本文帶你了解下Mysql的COUNT函數。
COUNT函數關(guān)于COUNT函數,在MySQL官網(wǎng)中有詳細介紹:
翻譯一下:
COUNT(expr) ,返回SELECT語(yǔ)句檢索的行中expr的值不為NULL的數量,結果是一個(gè)BIGINT值。0COUNT(*) 的統計結果中,會(huì )包含值為NULL的行數。在《阿里巴巴Java開(kāi)發(fā)手冊》也有如下要求:
COUNT(列名)、COUNT(常量)和COUNT(*)前面我們提到過(guò)
COUNT(expr)用于做行數統計,那么COUNT(列名)、COUNT(常量)和COUNT(*)這三種語(yǔ)法中,expr分別是列名、 常量 和*。
COUNT(*)和COUNT(常量)在列名、常量和 *這三個(gè)條件中,常量是一個(gè)固定值,肯定不為NULL。*可以理解為查詢(xún)整行,所以肯定也不為NULL,那么就只有列名的查詢(xún)結果可能是NULL。
所以, COUNT(常量) 和 COUNT(*)表示的是直接查詢(xún)符合條件的數據庫表的行數。而COUNT(列名)表示的是查詢(xún)符合條件的列的值不為NULL的行數。
COUNT(*)和COUNT(1)區別COUNT(1)就是COUNT(常量),對于這二者到底有沒(méi)有區別:
COUNT(*)執行時(shí)會(huì )轉換成COUNT(1),所以COUNT(1)少了轉換步驟,所以更快。MySQL針對COUNT(*)做了特殊優(yōu)化,所以COUNT(*)更快。到底哪種說(shuō)法是對的?看下MySQL官方文檔:
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
通過(guò)文檔,對于COUNT(1)和COUNT(*),MySQL的優(yōu)化是完全一樣的,根本不存在誰(shuí)比誰(shuí)快!
COUNT(列名)相較于前兩者,COUNT(列名)的查詢(xún)就比較簡(jiǎn)單粗暴了,就是進(jìn)行全表掃描,然后判斷指定字段的值是不是為NULL,不為NULL則累加。
相比
COUNT(*),COUNT(列名)多了一個(gè)步驟就是判斷所查詢(xún)的字段是否為NULL,所以他的性能要比COUNT(*)慢。
here和group的條件查詢(xún)。
SQL92除了查詢(xún)得到結果集有區別之外,COUNT(*)相比COUNT(常量) 和 COUNT(列名)來(lái)講,COUNT(*)是SQL92定義的標準統計行數的語(yǔ)法,因為他是標準語(yǔ)法,所以MySQL數據庫對他進(jìn)行過(guò)很多優(yōu)化。
SQL92,是數據庫的一個(gè)ANSI/ISO標準。它定義了一種語(yǔ)言(SQL)以及數據庫的行為(事務(wù)、隔離級別等)。
COUNT(*)優(yōu)化因為COUNT(*)是SQL92定義的標準統計行數的語(yǔ)法,所以MySQL對其進(jìn)行了很多優(yōu)化:
MyISAM中會(huì )直接把表的總行數單獨記錄下來(lái)供COUNT(*)查詢(xún)InnoDB會(huì )在掃表的時(shí)候選擇最小的索引來(lái)降低成本。這些優(yōu)化的前提都是沒(méi)有進(jìn)行
where和group的條件查詢(xún),更多請參考MySQL 全表 COUNT(*) 簡(jiǎn)述
COUNT函數用于統計表行數,按照效率比較的話(huà):
count(*)=count(常量)>count(列名)
既然 count(*) 在查詢(xún)上依賴(lài)于所有的數據集,所以我們在設計上也需要盡量的規避全量 count。
通常情況我們針對可預見(jiàn)的 count 查詢(xún)會(huì )做適當的緩存,可以是 Redis,也可以是獨立的 MySQL count 表。
聯(lián)系客服