1、COUNT有幾種用法?
2、COUNT(字段名)和COUNT(*)的查詢結果有什麼不同?
3、COUNT(1)和COUNT(*)之間有什麼不同?
4、COUNT(1)和COUNT(*)之間的效率哪個更高?
5、爲什麼《阿里巴巴Java開發手冊》建議使用COUNT(*)
6、MySQL的MyISAM引擎對COUNT(*)做了哪些優化?
7、MySQL的InnoDB引擎對COUNT(*)做了哪些優化?
8、上面提到的MySQL對COUNT(*)做的優化,有一個關鍵的前提是什麼?
9、SELECT COUNT(*) 的時候,加不加where條件有差別嗎?
10、COUNT(*)、COUNT(1)和COUNT(字段名)的執行過程是怎樣的?
COUNT(*)
的統計結果中,會包含值爲NULL的行數。insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)
from #bla
results 7 3 2
COUNT(id)
和COUNT(*)
以外,還可以使用COUNT(常量)
(如COUNT(1)
)來統計行數,那麼這三條SQL語句有什麼區別呢?到底哪種效率更高呢?爲什麼《阿里巴巴Java開發手冊》中強制要求不讓使用 COUNT(列名)
或 COUNT(常量)
來替代 COUNT(*)
呢?COUNT(列名)、COUNT(常量)和COUNT(*)之間的區別
COUNT(expr)
用於做行數統計,統計的是expr不爲NULL的行數,那麼COUNT(列名)
、 COUNT(常量)
和 COUNT(*)
這三種語法中,expr分別是列名
、 常量
和 *
。列名
、 常量
和 *
這三個條件中,常量
是一個固定值,肯定不爲NULL。*
可以理解爲查詢整行,所以肯定也不爲NULL,那麼就只有列名
的查詢結果有可能是NULL了。COUNT(常量)
和 COUNT(*)
表示的是直接查詢符合條件的數據庫表的行數。而COUNT(列名)
表示的是查詢符合條件的列的值不爲NULL的行數。COUNT(*)
相比COUNT(常量)
和 COUNT(列名)
來講,COUNT(*)是SQL92定義的標準統計行數的語法,因爲他是標準語法,所以MySQL數據庫對他進行過很多優化。COUNT(*)的優化
COUNT(*)
是SQL92定義的標準統計行數的語法,所以MySQL數據庫對他進行過很多優化。那麼,具體都做過哪些事情呢?COUNT(*)
有關,那就是MyISAM不支持事務,MyISAM中的鎖是表級鎖;而InnoDB支持事務,並且支持行級鎖。SELECT COUNT(*) FROM tbl_name
語句,確實在掃表的過程中做了一些優化。前提是查詢語句中不包含WHERE或GROUP BY等條件。COUNT(*)和COUNT(1)
COUNT(*)
,接下來看看COUNT(1)
,對於,這二者到底有沒有區別,網上的說法衆說紛紜。COUNT(*)
執行時會轉換成COUNT(1)
,所以COUNT(1)少了轉換步驟,所以更快。COUNT(*)
做了特殊優化,所以COUNT(*)
更快。InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
same way
, no performance difference
。所以,對於COUNT(1)和COUNT(*),MySQL的優化是完全一樣的,根本不存在誰比誰快!COUNT(*)
和COUNT(1)
一樣,建議用哪個呢?COUNT(*)
!因爲這個是SQL92定義的標準統計行數的語法,而且本文只是基於MySQL做了分析,關於Oracle中的這個問題,也是衆說紛紜的呢。COUNT(字段)
COUNT(*)
,COUNT(字段)
多了一個步驟就是判斷所查詢的字段是否爲NULL,所以他的性能要比COUNT(*)
慢。總結
COUNT(*)
、COUNT(字段)
和COUNT(1)
。COUNT(*)
是SQL92定義的標準統計行數的語法,所以MySQL對他進行了很多優化,MyISAM中會直接把表的總行數單獨記錄下來供COUNT(*)
查詢,而InnoDB則會在掃表的時候選擇最小的索引來降低成本。當然,這些優化的前提都是沒有進行where和group的條件查詢。COUNT(*)
和COUNT(1)
實現上沒有區別,而且效率一樣,但是COUNT(字段)
需要進行字段的非NULL判斷,所以效率會低一些。COUNT(*)
是SQL92定義的標準統計行數的語法,並且效率高,所以請直接使用COUNT(*)
查詢表的行數!參考資料:
https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_count
《極客時間——MySQL實戰45講》
推薦閱讀
公衆號@陳樹義,用最簡單的語言,分享我的技術見解。